Merge "Update contexthub OWNERS"
am: 9d71718e40
Change-Id: I2a125cafb0569b43d29cab49feb433edf098a5b6
diff --git a/drm/1.1/vts/functional/drm_hal_clearkey_test.cpp b/drm/1.1/vts/functional/drm_hal_clearkey_test.cpp
index 7dedd7f..6be30d3 100644
--- a/drm/1.1/vts/functional/drm_hal_clearkey_test.cpp
+++ b/drm/1.1/vts/functional/drm_hal_clearkey_test.cpp
@@ -24,7 +24,7 @@
#include <android/hardware/drm/1.0/types.h>
#include <android/hardware/drm/1.1/types.h>
#include <android/hidl/allocator/1.0/IAllocator.h>
-#include <android/hidl/manager/1.0/IServiceManager.h>
+#include <android/hidl/manager/1.2/IServiceManager.h>
#include <gtest/gtest.h>
#include <hidl/HidlSupport.h>
#include <hidl/ServiceManagement.h>
@@ -129,9 +129,9 @@
ALOGD("DrmHalClearkeyTest: Running test %s.%s", test_info->test_case_name(),
test_info->name());
- auto manager = android::hardware::defaultServiceManager();
+ auto manager = android::hardware::defaultServiceManager1_2();
ASSERT_NE(nullptr, manager.get());
- manager->listByInterface(IDrmFactory::descriptor,
+ manager->listManifestByInterface(IDrmFactory::descriptor,
[&](const hidl_vec<hidl_string> ®istered) {
for (const auto &instance : registered) {
sp<IDrmFactory> drmFactory =
@@ -144,7 +144,7 @@
}
);
- manager->listByInterface(ICryptoFactory::descriptor,
+ manager->listManifestByInterface(ICryptoFactory::descriptor,
[&](const hidl_vec<hidl_string> ®istered) {
for (const auto &instance : registered) {
sp<ICryptoFactory> cryptoFactory =
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 2d901f3..ee236ba 100644
--- a/gnss/1.1/vts/functional/gnss_hal_test_cases.cpp
+++ b/gnss/1.1/vts/functional/gnss_hal_test_cases.cpp
@@ -24,6 +24,9 @@
using android::hardware::hidl_vec;
+using IGnssMeasurement_1_0 = android::hardware::gnss::V1_0::IGnssMeasurement;
+using IGnssMeasurement_1_1 = android::hardware::gnss::V1_1::IGnssMeasurement;
+
using android::hardware::gnss::V1_0::GnssConstellationType;
using android::hardware::gnss::V1_0::GnssLocation;
using android::hardware::gnss::V1_0::IGnssDebug;
@@ -43,11 +46,15 @@
* Gets the GnssMeasurementExtension and verify that it returns an actual extension.
*/
TEST_F(GnssHalTest, TestGnssMeasurementCallback) {
- auto gnssMeasurement = gnss_hal_->getExtensionGnssMeasurement_1_1();
- ASSERT_TRUE(gnssMeasurement.isOk());
+ auto gnssMeasurement_1_1 = gnss_hal_->getExtensionGnssMeasurement_1_1();
+ ASSERT_TRUE(gnssMeasurement_1_1.isOk());
+ auto gnssMeasurement_1_0 = gnss_hal_->getExtensionGnssMeasurement();
+ ASSERT_TRUE(gnssMeasurement_1_0.isOk());
if (last_capabilities_ & IGnssCallback::Capabilities::MEASUREMENTS) {
- sp<IGnssMeasurement> iGnssMeas = gnssMeasurement;
- EXPECT_NE(iGnssMeas, nullptr);
+ sp<IGnssMeasurement_1_1> iGnssMeas_1_1 = gnssMeasurement_1_1;
+ sp<IGnssMeasurement_1_0> iGnssMeas_1_0 = gnssMeasurement_1_0;
+ // At least one interface must be non-null.
+ ASSERT_TRUE(iGnssMeas_1_1 != nullptr || iGnssMeas_1_0 != nullptr);
}
}
@@ -59,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;
@@ -202,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;
@@ -323,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/radio/1.2/vts/functional/radio_hidl_hal_test.cpp b/radio/1.2/vts/functional/radio_hidl_hal_test.cpp
index 835d9b8..21caddb 100644
--- a/radio/1.2/vts/functional/radio_hidl_hal_test.cpp
+++ b/radio/1.2/vts/functional/radio_hidl_hal_test.cpp
@@ -14,7 +14,6 @@
* limitations under the License.
*/
-#include <android/hardware/radio/1.1/IRadio.h>
#include <radio_hidl_hal_utils_v1_2.h>
void RadioHidlTest_v1_2::SetUp() {
@@ -154,25 +153,7 @@
}
void RadioHidlTest_v1_2::stopNetworkScan() {
- sp<::android::hardware::radio::V1_1::IRadio> radio_v1_1;
-
- radio_v1_1 = ::testing::VtsHalHidlTargetTestBase::getService<
- ::android::hardware::radio::V1_1::IRadio>(
- RadioHidlEnvironment::Instance()
- ->getServiceName<::android::hardware::radio::V1_1::IRadio>(
- hidl_string(RADIO_SERVICE_NAME)));
- if (radio_v1_1 == NULL) {
- sleep(60);
- radio_v1_1 = ::testing::VtsHalHidlTargetTestBase::getService<
- ::android::hardware::radio::V1_1::IRadio>(
- RadioHidlEnvironment::Instance()
- ->getServiceName<::android::hardware::radio::V1_1::IRadio>(
- hidl_string(RADIO_SERVICE_NAME)));
- }
- ASSERT_NE(nullptr, radio_v1_1.get());
-
serial = GetRandomSerialNumber();
-
- radio_v1_1->stopNetworkScan(serial);
+ radio_v1_2->stopNetworkScan(serial);
EXPECT_EQ(std::cv_status::no_timeout, wait());
}
diff --git a/radio/1.4/vts/functional/radio_hidl_hal_api.cpp b/radio/1.4/vts/functional/radio_hidl_hal_api.cpp
index b2d19a2..bf225bc 100644
--- a/radio/1.4/vts/functional/radio_hidl_hal_api.cpp
+++ b/radio/1.4/vts/functional/radio_hidl_hal_api.cpp
@@ -169,6 +169,11 @@
/*
* Test IRadio.startNetworkScan() for the response returned.
+ *
+ * REQUEST_NOT_SUPPORTED is temporarily returned because of vendors failed to fully implement
+ * startNetworkScan in HAL @1.4 (see b/137298570 and b/135595082). Starting from @1.5, however,
+ * REQUEST_NOT_SUPPORTED will be disallowed for all tests. Modems have "GSM" rat scan need to
+ * support scanning requests combined with some parameters.
*/
TEST_F(RadioHidlTest_v1_4, startNetworkScan) {
serial = GetRandomSerialNumber();
@@ -191,10 +196,17 @@
if (cardStatus.base.base.cardState == CardState::ABSENT) {
ASSERT_TRUE(CheckAnyOfErrors(radioRsp_v1_4->rspInfo.error, {RadioError::SIM_ABSENT}));
} else if (cardStatus.base.base.cardState == CardState::PRESENT) {
- // OPERATION_NOT_ALLOWED should not be allowed; however, some vendors do not support the
- // required manual GSM search functionality. This is tracked in b/112206766.
- ASSERT_TRUE(CheckAnyOfErrors(radioRsp_v1_4->rspInfo.error,
- {RadioError::NONE, RadioError::OPERATION_NOT_ALLOWED}));
+ // OPERATION_NOT_ALLOWED should not be allowed; however, some vendors do
+ // not support the required manual GSM search functionality. This is
+ // tracked in b/112206766. REQUEST_NOT_SUPPORTED is temporarily added back
+ // because of vendors failed to implement startNetworkScan in HAL 1.4 (see
+ // b/137298570 and b/135595082). Starting from 1.5, however,
+ // REQUEST_NOT_SUPPORTED will be disallowed. Modems have "GSM" rat scan
+ // need to support scanning requests combined with some parameters.
+ ASSERT_TRUE(
+ CheckAnyOfErrors(radioRsp_v1_4->rspInfo.error,
+ {RadioError::NONE, RadioError::OPERATION_NOT_ALLOWED,
+ RadioError::REQUEST_NOT_SUPPORTED}));
}
}
@@ -220,8 +232,9 @@
ASSERT_TRUE(CheckAnyOfErrors(radioRsp_v1_4->rspInfo.error,
{RadioError::SIM_ABSENT, RadioError::INVALID_ARGUMENTS}));
} else if (cardStatus.base.base.cardState == CardState::PRESENT) {
- ASSERT_TRUE(
- CheckAnyOfErrors(radioRsp_v1_4->rspInfo.error, {RadioError::INVALID_ARGUMENTS}));
+ ASSERT_TRUE(CheckAnyOfErrors(
+ radioRsp_v1_4->rspInfo.error,
+ {RadioError::INVALID_ARGUMENTS, RadioError::REQUEST_NOT_SUPPORTED}));
}
}
@@ -256,8 +269,9 @@
ASSERT_TRUE(CheckAnyOfErrors(radioRsp_v1_4->rspInfo.error,
{RadioError::SIM_ABSENT, RadioError::INVALID_ARGUMENTS}));
} else if (cardStatus.base.base.cardState == CardState::PRESENT) {
- ASSERT_TRUE(
- CheckAnyOfErrors(radioRsp_v1_4->rspInfo.error, {RadioError::INVALID_ARGUMENTS}));
+ ASSERT_TRUE(CheckAnyOfErrors(
+ radioRsp_v1_4->rspInfo.error,
+ {RadioError::INVALID_ARGUMENTS, RadioError::REQUEST_NOT_SUPPORTED}));
}
}
@@ -291,8 +305,9 @@
ASSERT_TRUE(CheckAnyOfErrors(radioRsp_v1_4->rspInfo.error,
{RadioError::SIM_ABSENT, RadioError::INVALID_ARGUMENTS}));
} else if (cardStatus.base.base.cardState == CardState::PRESENT) {
- ASSERT_TRUE(
- CheckAnyOfErrors(radioRsp_v1_4->rspInfo.error, {RadioError::INVALID_ARGUMENTS}));
+ ASSERT_TRUE(CheckAnyOfErrors(
+ radioRsp_v1_4->rspInfo.error,
+ {RadioError::INVALID_ARGUMENTS, RadioError::REQUEST_NOT_SUPPORTED}));
}
}
@@ -326,8 +341,9 @@
ASSERT_TRUE(CheckAnyOfErrors(radioRsp_v1_4->rspInfo.error,
{RadioError::SIM_ABSENT, RadioError::INVALID_ARGUMENTS}));
} else if (cardStatus.base.base.cardState == CardState::PRESENT) {
- ASSERT_TRUE(
- CheckAnyOfErrors(radioRsp_v1_4->rspInfo.error, {RadioError::INVALID_ARGUMENTS}));
+ ASSERT_TRUE(CheckAnyOfErrors(
+ radioRsp_v1_4->rspInfo.error,
+ {RadioError::INVALID_ARGUMENTS, RadioError::REQUEST_NOT_SUPPORTED}));
}
}
@@ -361,8 +377,9 @@
ASSERT_TRUE(CheckAnyOfErrors(radioRsp_v1_4->rspInfo.error,
{RadioError::SIM_ABSENT, RadioError::INVALID_ARGUMENTS}));
} else if (cardStatus.base.base.cardState == CardState::PRESENT) {
- ASSERT_TRUE(
- CheckAnyOfErrors(radioRsp_v1_4->rspInfo.error, {RadioError::INVALID_ARGUMENTS}));
+ ASSERT_TRUE(CheckAnyOfErrors(
+ radioRsp_v1_4->rspInfo.error,
+ {RadioError::INVALID_ARGUMENTS, RadioError::REQUEST_NOT_SUPPORTED}));
}
}
@@ -396,8 +413,9 @@
ASSERT_TRUE(CheckAnyOfErrors(radioRsp_v1_4->rspInfo.error,
{RadioError::SIM_ABSENT, RadioError::INVALID_ARGUMENTS}));
} else if (cardStatus.base.base.cardState == CardState::PRESENT) {
- ASSERT_TRUE(
- CheckAnyOfErrors(radioRsp_v1_4->rspInfo.error, {RadioError::INVALID_ARGUMENTS}));
+ ASSERT_TRUE(CheckAnyOfErrors(
+ radioRsp_v1_4->rspInfo.error,
+ {RadioError::INVALID_ARGUMENTS, RadioError::REQUEST_NOT_SUPPORTED}));
}
}
@@ -431,8 +449,9 @@
ASSERT_TRUE(CheckAnyOfErrors(radioRsp_v1_4->rspInfo.error,
{RadioError::SIM_ABSENT, RadioError::INVALID_ARGUMENTS}));
} else if (cardStatus.base.base.cardState == CardState::PRESENT) {
- ASSERT_TRUE(
- CheckAnyOfErrors(radioRsp_v1_4->rspInfo.error, {RadioError::INVALID_ARGUMENTS}));
+ ASSERT_TRUE(CheckAnyOfErrors(
+ radioRsp_v1_4->rspInfo.error,
+ {RadioError::INVALID_ARGUMENTS, RadioError::REQUEST_NOT_SUPPORTED}));
}
}
@@ -468,8 +487,10 @@
ASSERT_TRUE(CheckAnyOfErrors(radioRsp_v1_4->rspInfo.error,
{RadioError::NONE, RadioError::SIM_ABSENT}));
} else if (cardStatus.base.base.cardState == CardState::PRESENT) {
- ASSERT_TRUE(CheckAnyOfErrors(radioRsp_v1_4->rspInfo.error,
- {RadioError::NONE, RadioError::INVALID_ARGUMENTS}));
+ ASSERT_TRUE(
+ CheckAnyOfErrors(radioRsp_v1_4->rspInfo.error,
+ {RadioError::NONE, RadioError::INVALID_ARGUMENTS,
+ RadioError::REQUEST_NOT_SUPPORTED}));
}
}
@@ -507,8 +528,10 @@
ASSERT_TRUE(CheckAnyOfErrors(radioRsp_v1_4->rspInfo.error,
{RadioError::NONE, RadioError::SIM_ABSENT}));
} else if (cardStatus.base.base.cardState == CardState::PRESENT) {
- ASSERT_TRUE(CheckAnyOfErrors(radioRsp_v1_4->rspInfo.error,
- {RadioError::NONE, RadioError::INVALID_ARGUMENTS}));
+ ASSERT_TRUE(
+ CheckAnyOfErrors(radioRsp_v1_4->rspInfo.error,
+ {RadioError::NONE, RadioError::INVALID_ARGUMENTS,
+ RadioError::REQUEST_NOT_SUPPORTED}));
}
}
diff --git a/sensors/1.0/vts/functional/Android.bp b/sensors/1.0/vts/functional/Android.bp
index d4c5f32..7bb992b 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",
@@ -23,7 +24,10 @@
],
static_libs: [
"android.hardware.graphics.allocator@2.0",
+ "android.hardware.graphics.allocator@3.0",
"android.hardware.graphics.mapper@2.0",
+ "android.hardware.graphics.mapper@2.1",
+ "android.hardware.graphics.mapper@3.0",
"android.hardware.sensors@1.0",
"VtsHalSensorsTargetTestUtils",
],
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..4765fa2 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",
@@ -23,7 +24,10 @@
],
static_libs: [
"android.hardware.graphics.allocator@2.0",
+ "android.hardware.graphics.allocator@3.0",
"android.hardware.graphics.mapper@2.0",
+ "android.hardware.graphics.mapper@2.1",
+ "android.hardware.graphics.mapper@3.0",
"android.hardware.sensors@1.0",
"android.hardware.sensors@2.0",
"libfmq",
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..8364ba9 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
@@ -169,19 +176,21 @@
// Helper functions
void activateAllSensors(bool enable);
std::vector<SensorInfo> getNonOneShotSensors();
+ std::vector<SensorInfo> getNonOneShotAndNonSpecialSensors();
std::vector<SensorInfo> getOneShotSensors();
std::vector<SensorInfo> getInjectEventSensors();
int32_t getInvalidSensorHandle();
bool getDirectChannelSensor(SensorInfo* sensor, SharedMemType* memType, RateLevel* rate);
void verifyDirectChannel(SharedMemType memType);
- void verifyRegisterDirectChannel(const SensorInfo& sensor, SharedMemType memType,
- std::shared_ptr<SensorsTestSharedMemory> mem,
- int32_t* directChannelHandle);
+ void verifyRegisterDirectChannel(std::shared_ptr<SensorsTestSharedMemory> mem,
+ int32_t* directChannelHandle, bool supportsSharedMemType,
+ bool supportsAnyDirectChannel);
void verifyConfigure(const SensorInfo& sensor, SharedMemType memType,
- int32_t directChannelHandle);
- void verifyUnregisterDirectChannel(const SensorInfo& sensor, SharedMemType memType,
- int32_t directChannelHandle);
+ int32_t directChannelHandle, bool directChannelSupported);
+ void verifyUnregisterDirectChannel(int32_t directChannelHandle, bool directChannelSupported);
void checkRateLevel(const SensorInfo& sensor, int32_t directChannelHandle, RateLevel rateLevel);
+ void queryDirectChannelSupport(SharedMemType memType, bool* supportsSharedMemType,
+ bool* supportsAnyDirectChannel);
};
Return<Result> SensorsHidlTest::activate(int32_t sensorHandle, bool enabled) {
@@ -250,6 +259,18 @@
return sensors;
}
+std::vector<SensorInfo> SensorsHidlTest::getNonOneShotAndNonSpecialSensors() {
+ std::vector<SensorInfo> sensors;
+ for (const SensorInfo& info : getSensorsList()) {
+ SensorFlagBits reportMode = extractReportMode(info.flags);
+ if (reportMode != SensorFlagBits::ONE_SHOT_MODE &&
+ reportMode != SensorFlagBits::SPECIAL_REPORTING_MODE) {
+ sensors.push_back(info);
+ }
+ }
+ return sensors;
+}
+
std::vector<SensorInfo> SensorsHidlTest::getOneShotSensors() {
std::vector<SensorInfo> sensors;
for (const SensorInfo& info : getSensorsList()) {
@@ -368,7 +389,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 +635,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 +650,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 +673,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 +716,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.
@@ -761,7 +791,12 @@
activateAllSensors(false /* enable */);
for (const SensorInfo& sensor : getSensorsList()) {
// Call batch on inactive sensor
- ASSERT_EQ(batch(sensor.sensorHandle, sensor.minDelay, 0 /* maxReportLatencyNs */),
+ // One shot sensors have minDelay set to -1 which is an invalid
+ // parameter. Use 0 instead to avoid errors.
+ int64_t samplingPeriodNs = extractReportMode(sensor.flags) == SensorFlagBits::ONE_SHOT_MODE
+ ? 0
+ : sensor.minDelay;
+ ASSERT_EQ(batch(sensor.sensorHandle, samplingPeriodNs, 0 /* maxReportLatencyNs */),
Result::OK);
// Activate the sensor
@@ -807,17 +842,19 @@
}
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;
- for (const SensorInfo& sensor : getSensorsList()) {
- maxMinDelay = std::max(maxMinDelay, sensor.minDelay);
+ // This test is not valid for one-shot or special-report-mode sensors
+ const std::vector<SensorInfo> sensors = getNonOneShotAndNonSpecialSensors();
+ milliseconds maxMinDelay(0);
+ for (const SensorInfo& sensor : sensors) {
+ 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,33 +863,46 @@
// 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
std::map<int32_t, int64_t> lastEventTimestampMap;
for (const SensorInfo& sensor : sensors) {
- ASSERT_GE(callback.getEvents(sensor.sensorHandle).size(), 1);
- lastEventTimestampMap[sensor.sensorHandle] =
- callback.getEvents(sensor.sensorHandle).back().timestamp;
+ // Some on-change sensors may not report an event without stimulus
+ if (extractReportMode(sensor.flags) != SensorFlagBits::ON_CHANGE_MODE) {
+ ASSERT_GE(callback.getEvents(sensor.sensorHandle).size(), 1);
+ }
+ if (callback.getEvents(sensor.sensorHandle).size() >= 1) {
+ lastEventTimestampMap[sensor.sensorHandle] =
+ callback.getEvents(sensor.sensorHandle).back().timestamp;
+ }
}
// 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) {
+ // Skip sensors that did not previously report an event
+ if (lastEventTimestampMap.find(sensor.sensorHandle) == lastEventTimestampMap.end()) {
+ continue;
+ }
+ // Skip on-change sensors that do not consistently report an initial event
+ if (callback.getEvents(sensor.sensorHandle).size() < 1) {
+ continue;
+ }
// 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,
@@ -861,21 +911,43 @@
[&](Result result, int32_t reportToken) {
if (isDirectReportRateSupported(sensor, rateLevel)) {
ASSERT_EQ(result, Result::OK);
- ASSERT_GT(reportToken, 0);
+ if (rateLevel != RateLevel::STOP) {
+ ASSERT_GT(reportToken, 0);
+ }
} else {
ASSERT_EQ(result, Result::BAD_VALUE);
}
});
}
-void SensorsHidlTest::verifyRegisterDirectChannel(const SensorInfo& sensor, SharedMemType memType,
- std::shared_ptr<SensorsTestSharedMemory> mem,
- int32_t* directChannelHandle) {
+void SensorsHidlTest::queryDirectChannelSupport(SharedMemType memType, bool* supportsSharedMemType,
+ bool* supportsAnyDirectChannel) {
+ *supportsSharedMemType = false;
+ *supportsAnyDirectChannel = false;
+ for (const SensorInfo& curSensor : getSensorsList()) {
+ if (isDirectChannelTypeSupported(curSensor, memType)) {
+ *supportsSharedMemType = true;
+ }
+ if (isDirectChannelTypeSupported(curSensor, SharedMemType::ASHMEM) ||
+ isDirectChannelTypeSupported(curSensor, SharedMemType::GRALLOC)) {
+ *supportsAnyDirectChannel = true;
+ }
+
+ if (*supportsSharedMemType && *supportsAnyDirectChannel) {
+ break;
+ }
+ }
+}
+
+void SensorsHidlTest::verifyRegisterDirectChannel(std::shared_ptr<SensorsTestSharedMemory> mem,
+ int32_t* directChannelHandle,
+ bool supportsSharedMemType,
+ bool supportsAnyDirectChannel) {
char* buffer = mem->getBuffer();
memset(buffer, 0xff, mem->getSize());
registerDirectChannel(mem->getSharedMemInfo(), [&](Result result, int32_t channelHandle) {
- if (isDirectChannelTypeSupported(sensor, memType)) {
+ if (supportsSharedMemType) {
ASSERT_EQ(result, Result::OK);
ASSERT_GT(channelHandle, 0);
@@ -884,7 +956,9 @@
ASSERT_EQ(buffer[i], 0x00);
}
} else {
- ASSERT_EQ(result, Result::INVALID_OPERATION);
+ Result expectedResult =
+ supportsAnyDirectChannel ? Result::BAD_VALUE : Result::INVALID_OPERATION;
+ ASSERT_EQ(result, expectedResult);
ASSERT_EQ(channelHandle, -1);
}
*directChannelHandle = channelHandle;
@@ -892,7 +966,7 @@
}
void SensorsHidlTest::verifyConfigure(const SensorInfo& sensor, SharedMemType memType,
- int32_t directChannelHandle) {
+ int32_t directChannelHandle, bool supportsAnyDirectChannel) {
if (isDirectChannelTypeSupported(sensor, memType)) {
// Verify that each rate level is properly supported
checkRateLevel(sensor, directChannelHandle, RateLevel::NORMAL);
@@ -908,22 +982,22 @@
-1 /* sensorHandle */, directChannelHandle, RateLevel::STOP,
[](Result result, int32_t /* reportToken */) { ASSERT_EQ(result, Result::OK); });
} else {
- // Direct channel is not supported for this SharedMemType
+ // directChannelHandle will be -1 here, HAL should either reject it as a bad value if there
+ // is some level of direct channel report, otherwise return INVALID_OPERATION if direct
+ // channel is not supported at all
+ Result expectedResult =
+ supportsAnyDirectChannel ? Result::BAD_VALUE : Result::INVALID_OPERATION;
configDirectReport(sensor.sensorHandle, directChannelHandle, RateLevel::NORMAL,
- [](Result result, int32_t /* reportToken */) {
- ASSERT_EQ(result, Result::INVALID_OPERATION);
+ [expectedResult](Result result, int32_t /* reportToken */) {
+ ASSERT_EQ(result, expectedResult);
});
}
}
-void SensorsHidlTest::verifyUnregisterDirectChannel(const SensorInfo& sensor, SharedMemType memType,
- int32_t directChannelHandle) {
- Result result = unregisterDirectChannel(directChannelHandle);
- if (isDirectChannelTypeSupported(sensor, memType)) {
- ASSERT_EQ(result, Result::OK);
- } else {
- ASSERT_EQ(result, Result::INVALID_OPERATION);
- }
+void SensorsHidlTest::verifyUnregisterDirectChannel(int32_t directChannelHandle,
+ bool supportsAnyDirectChannel) {
+ Result expectedResult = supportsAnyDirectChannel ? Result::OK : Result::INVALID_OPERATION;
+ ASSERT_EQ(unregisterDirectChannel(directChannelHandle), expectedResult);
}
void SensorsHidlTest::verifyDirectChannel(SharedMemType memType) {
@@ -934,11 +1008,16 @@
SensorsTestSharedMemory::create(memType, kMemSize));
ASSERT_NE(mem, nullptr);
+ bool supportsSharedMemType;
+ bool supportsAnyDirectChannel;
+ queryDirectChannelSupport(memType, &supportsSharedMemType, &supportsAnyDirectChannel);
+
for (const SensorInfo& sensor : getSensorsList()) {
int32_t directChannelHandle = 0;
- verifyRegisterDirectChannel(sensor, memType, mem, &directChannelHandle);
- verifyConfigure(sensor, memType, directChannelHandle);
- verifyUnregisterDirectChannel(sensor, memType, directChannelHandle);
+ verifyRegisterDirectChannel(mem, &directChannelHandle, supportsSharedMemType,
+ supportsAnyDirectChannel);
+ verifyConfigure(sensor, memType, directChannelHandle, supportsAnyDirectChannel);
+ verifyUnregisterDirectChannel(directChannelHandle, supportsAnyDirectChannel);
}
}
@@ -1030,8 +1109,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..02dc608 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",
@@ -30,7 +31,10 @@
],
static_libs: [
"android.hardware.graphics.allocator@2.0",
+ "android.hardware.graphics.allocator@3.0",
"android.hardware.graphics.mapper@2.0",
+ "android.hardware.graphics.mapper@2.1",
+ "android.hardware.graphics.mapper@3.0",
"android.hardware.sensors@1.0",
"VtsHalHidlTargetTestBase",
],
diff --git a/sensors/common/vts/utils/GrallocWrapper.cpp b/sensors/common/vts/utils/GrallocWrapper.cpp
index 7bed16d..1cad913 100644
--- a/sensors/common/vts/utils/GrallocWrapper.cpp
+++ b/sensors/common/vts/utils/GrallocWrapper.cpp
@@ -14,211 +14,264 @@
* limitations under the License.
*/
-#define LOG_TAG "GrallocWrapper"
-
#include "GrallocWrapper.h"
+#include <android/hardware/graphics/allocator/2.0/IAllocator.h>
+#include <android/hardware/graphics/allocator/3.0/IAllocator.h>
+#include <android/hardware/graphics/mapper/2.0/IMapper.h>
+#include <android/hardware/graphics/mapper/2.1/IMapper.h>
+#include <android/hardware/graphics/mapper/3.0/IMapper.h>
+
#include <utils/Log.h>
+#include <cinttypes>
+#include <type_traits>
+
+using IAllocator2 = ::android::hardware::graphics::allocator::V2_0::IAllocator;
+using IAllocator3 = ::android::hardware::graphics::allocator::V3_0::IAllocator;
+using IMapper2 = ::android::hardware::graphics::mapper::V2_0::IMapper;
+using IMapper2_1 = ::android::hardware::graphics::mapper::V2_1::IMapper;
+using IMapper3 = ::android::hardware::graphics::mapper::V3_0::IMapper;
+
+using Error2 = ::android::hardware::graphics::mapper::V2_0::Error;
+using Error3 = ::android::hardware::graphics::mapper::V3_0::Error;
+
+using ::android::hardware::graphics::common::V1_0::BufferUsage;
+using ::android::hardware::graphics::common::V1_0::PixelFormat;
+
+// This is a typedef to the same underlying type across v2.0 and v3.0
+using ::android::hardware::graphics::mapper::V2_0::BufferDescriptor;
+
+using ::android::hardware::hidl_handle;
+using ::android::hardware::hidl_string;
+using ::android::hardware::hidl_vec;
+
namespace android {
-GrallocWrapper::GrallocWrapper() {
- init();
+// Since we use the same APIs across allocator/mapper HALs but they have major
+// version differences (meaning they are not related through inheritance), we
+// create a common interface abstraction for the IAllocator + IMapper combination
+// (major versions need to match in the current HALs, e.g. IAllocator 3.0 needs to
+// be paired with IMapper 3.0, so these are tied together)
+class IGrallocHalWrapper {
+ public:
+ virtual ~IGrallocHalWrapper() = default;
+
+ // IAllocator
+ virtual std::string dumpDebugInfo() = 0;
+ virtual native_handle_t* allocate(uint32_t size) = 0;
+ virtual void freeBuffer(native_handle_t* bufferHandle) = 0;
+
+ // IMapper
+ virtual void* lock(native_handle_t* bufferHandle) = 0;
+ virtual void unlock(native_handle_t* bufferHandle) = 0;
+};
+
+namespace {
+
+bool failed(Error2 error) {
+ return (error != Error2::NONE);
+}
+bool failed(Error3 error) {
+ return (error != Error3::NONE);
}
-void GrallocWrapper::init() {
- mAllocator = allocator2::IAllocator::getService();
- if (mAllocator == nullptr) {
- ALOGE("Failed to get allocator service");
- }
-
- mMapper = mapper2::IMapper::getService();
- if (mMapper == nullptr) {
- ALOGE("Failed to get mapper service");
- }
- if (mMapper->isRemote()) {
- ALOGE("Mapper is not in passthrough mode");
- }
-}
-
-GrallocWrapper::~GrallocWrapper() {
- for (auto bufferHandle : mClonedBuffers) {
- auto buffer = const_cast<native_handle_t*>(bufferHandle);
- native_handle_close(buffer);
- native_handle_delete(buffer);
- }
- mClonedBuffers.clear();
-
- for (auto bufferHandle : mImportedBuffers) {
- auto buffer = const_cast<native_handle_t*>(bufferHandle);
- if (mMapper->freeBuffer(buffer) != mapper2::Error::NONE) {
- ALOGE("Failed to free buffer %p", buffer);
+// Since all the type and function names are the same for the things we use across the major HAL
+// versions, we use template magic to avoid repeating ourselves.
+template <typename AllocatorT, typename MapperT>
+class GrallocHalWrapper : public IGrallocHalWrapper {
+ public:
+ GrallocHalWrapper(const sp<AllocatorT>& allocator, const sp<MapperT>& mapper)
+ : mAllocator(allocator), mMapper(mapper) {
+ if (mapper->isRemote()) {
+ ALOGE("Mapper is in passthrough mode");
}
}
- mImportedBuffers.clear();
-}
-sp<allocator2::IAllocator> GrallocWrapper::getAllocator() const {
- return mAllocator;
-}
+ virtual std::string dumpDebugInfo() override;
+ virtual native_handle_t* allocate(uint32_t size) override;
+ virtual void freeBuffer(native_handle_t* bufferHandle) override;
-std::string GrallocWrapper::dumpDebugInfo() {
+ virtual void* lock(native_handle_t* bufferHandle) override;
+ virtual void unlock(native_handle_t* bufferHandle) override;
+
+ private:
+ static constexpr uint64_t kBufferUsage =
+ static_cast<uint64_t>(BufferUsage::SENSOR_DIRECT_DATA | BufferUsage::CPU_READ_OFTEN);
+ sp<AllocatorT> mAllocator;
+ sp<MapperT> mMapper;
+
+ BufferDescriptor getDescriptor(uint32_t size);
+ native_handle_t* importBuffer(const hidl_handle& rawHandle);
+};
+
+template <typename AllocatorT, typename MapperT>
+std::string GrallocHalWrapper<AllocatorT, MapperT>::dumpDebugInfo() {
std::string debugInfo;
- mAllocator->dumpDebugInfo([&](const auto& tmpDebugInfo) { debugInfo = tmpDebugInfo.c_str(); });
-
+ mAllocator->dumpDebugInfo([&](const hidl_string& tmpDebugInfo) { debugInfo = tmpDebugInfo; });
return debugInfo;
}
-const native_handle_t* GrallocWrapper::cloneBuffer(const hardware::hidl_handle& rawHandle) {
- const native_handle_t* bufferHandle = native_handle_clone(rawHandle.getNativeHandle());
+template <typename AllocatorT, typename MapperT>
+native_handle_t* GrallocHalWrapper<AllocatorT, MapperT>::allocate(uint32_t size) {
+ constexpr uint32_t kBufferCount = 1;
+ BufferDescriptor descriptor = getDescriptor(size);
+ native_handle_t* bufferHandle = nullptr;
- if (bufferHandle) {
- mClonedBuffers.insert(bufferHandle);
- }
+ auto callback = [&](auto error, uint32_t /*stride*/, const hidl_vec<hidl_handle>& buffers) {
+ if (failed(error)) {
+ ALOGE("Failed to allocate buffer: %" PRId32, static_cast<int32_t>(error));
+ } else if (buffers.size() != kBufferCount) {
+ ALOGE("Invalid buffer array size (got %zu, expected %" PRIu32 ")", buffers.size(),
+ kBufferCount);
+ } else {
+ bufferHandle = importBuffer(buffers[0]);
+ }
+ };
+
+ mAllocator->allocate(descriptor, kBufferCount, callback);
return bufferHandle;
}
-std::vector<const native_handle_t*> GrallocWrapper::allocate(
- const mapper2::BufferDescriptor& descriptor, uint32_t count, bool import, uint32_t* outStride) {
- std::vector<const native_handle_t*> bufferHandles;
- bufferHandles.reserve(count);
- mAllocator->allocate(descriptor, count,
- [&](const auto& tmpError, const auto& tmpStride, const auto& tmpBuffers) {
- if (mapper2::Error::NONE != tmpError) {
- ALOGE("Failed to allocate buffers");
- }
- if (count != tmpBuffers.size()) {
- ALOGE("Invalid buffer array");
- }
-
- for (uint32_t i = 0; i < count; i++) {
- if (import) {
- bufferHandles.push_back(importBuffer(tmpBuffers[i]));
- } else {
- bufferHandles.push_back(cloneBuffer(tmpBuffers[i]));
- }
- }
-
- if (outStride) {
- *outStride = tmpStride;
- }
- });
-
- return bufferHandles;
+template <typename AllocatorT, typename MapperT>
+void GrallocHalWrapper<AllocatorT, MapperT>::freeBuffer(native_handle_t* bufferHandle) {
+ auto error = mMapper->freeBuffer(bufferHandle);
+ if (!error.isOk() || failed(error)) {
+ ALOGE("Failed to free buffer %p", bufferHandle);
+ }
}
-const native_handle_t* GrallocWrapper::allocate(
- const mapper2::IMapper::BufferDescriptorInfo& descriptorInfo, bool import,
- uint32_t* outStride) {
- mapper2::BufferDescriptor descriptor = createDescriptor(descriptorInfo);
- auto buffers = allocate(descriptor, 1, import, outStride);
- return buffers[0];
-}
+template <typename AllocatorT, typename MapperT>
+BufferDescriptor GrallocHalWrapper<AllocatorT, MapperT>::getDescriptor(uint32_t size) {
+ typename MapperT::BufferDescriptorInfo descriptorInfo = {
+ .width = size,
+ .height = 1,
+ .layerCount = 1,
+ .usage = kBufferUsage,
+ .format = static_cast<decltype(descriptorInfo.format)>(PixelFormat::BLOB),
+ };
-sp<mapper2::IMapper> GrallocWrapper::getMapper() const {
- return mMapper;
-}
-
-mapper2::BufferDescriptor GrallocWrapper::createDescriptor(
- const mapper2::IMapper::BufferDescriptorInfo& descriptorInfo) {
- mapper2::BufferDescriptor descriptor;
- mMapper->createDescriptor(descriptorInfo, [&](const auto& tmpError, const auto& tmpDescriptor) {
- if (tmpError != mapper2::Error::NONE) {
- ALOGE("Failed to create descriptor");
+ BufferDescriptor descriptor;
+ auto callback = [&](auto error, const BufferDescriptor& tmpDescriptor) {
+ if (failed(error)) {
+ ALOGE("Failed to create descriptor: %" PRId32, static_cast<int32_t>(error));
+ } else {
+ descriptor = tmpDescriptor;
}
- descriptor = tmpDescriptor;
- });
+ };
+ mMapper->createDescriptor(descriptorInfo, callback);
return descriptor;
}
-const native_handle_t* GrallocWrapper::importBuffer(const hardware::hidl_handle& rawHandle) {
- const native_handle_t* bufferHandle = nullptr;
- mMapper->importBuffer(rawHandle, [&](const auto& tmpError, const auto& tmpBuffer) {
- if (tmpError != mapper2::Error::NONE) {
- ALOGE("Failed to import buffer %p", rawHandle.getNativeHandle());
- }
- bufferHandle = static_cast<const native_handle_t*>(tmpBuffer);
- });
+template <typename AllocatorT, typename MapperT>
+native_handle_t* GrallocHalWrapper<AllocatorT, MapperT>::importBuffer(
+ const hidl_handle& rawHandle) {
+ native_handle_t* bufferHandle = nullptr;
- if (bufferHandle) {
- mImportedBuffers.insert(bufferHandle);
- }
+ mMapper->importBuffer(rawHandle, [&](auto error, void* tmpBuffer) {
+ if (failed(error)) {
+ ALOGE("Failed to import buffer %p: %" PRId32, rawHandle.getNativeHandle(),
+ static_cast<int32_t>(error));
+ } else {
+ bufferHandle = static_cast<native_handle_t*>(tmpBuffer);
+ }
+ });
return bufferHandle;
}
-void GrallocWrapper::freeBuffer(const native_handle_t* bufferHandle) {
- auto buffer = const_cast<native_handle_t*>(bufferHandle);
-
- if (mImportedBuffers.erase(bufferHandle)) {
- mapper2::Error error = mMapper->freeBuffer(buffer);
- if (error != mapper2::Error::NONE) {
- ALOGE("Failed to free %p", buffer);
- }
- } else {
- mClonedBuffers.erase(bufferHandle);
- native_handle_close(buffer);
- native_handle_delete(buffer);
- }
-}
-
-void* GrallocWrapper::lock(const native_handle_t* bufferHandle, uint64_t cpuUsage,
- const mapper2::IMapper::Rect& accessRegion, int acquireFence) {
- auto buffer = const_cast<native_handle_t*>(bufferHandle);
-
- NATIVE_HANDLE_DECLARE_STORAGE(acquireFenceStorage, 1, 0);
- hardware::hidl_handle acquireFenceHandle;
- if (acquireFence >= 0) {
- auto h = native_handle_init(acquireFenceStorage, 1, 0);
- h->data[0] = acquireFence;
- acquireFenceHandle = h;
- }
+template <typename AllocatorT, typename MapperT>
+void* GrallocHalWrapper<AllocatorT, MapperT>::lock(native_handle_t* bufferHandle) {
+ // Per the HAL, all-zeros Rect means the entire buffer
+ typename MapperT::Rect accessRegion = {};
+ hidl_handle acquireFenceHandle; // No fence needed, already safe to lock
void* data = nullptr;
- mMapper->lock(buffer, cpuUsage, accessRegion, acquireFenceHandle,
- [&](const auto& tmpError, const auto& tmpData) {
- if (tmpError != mapper2::Error::NONE) {
- ALOGE("Failed to lock buffer %p", buffer);
+ mMapper->lock(bufferHandle, kBufferUsage, accessRegion, acquireFenceHandle,
+ [&](auto error, void* tmpData, ...) { // V3_0 passes extra args we don't use
+ if (failed(error)) {
+ ALOGE("Failed to lock buffer %p: %" PRId32, bufferHandle,
+ static_cast<int32_t>(error));
+ } else {
+ data = tmpData;
}
- data = tmpData;
});
- if (acquireFence >= 0) {
- close(acquireFence);
- }
-
return data;
}
-int GrallocWrapper::unlock(const native_handle_t* bufferHandle) {
- auto buffer = const_cast<native_handle_t*>(bufferHandle);
-
- int releaseFence = -1;
- mMapper->unlock(buffer, [&](const auto& tmpError, const auto& tmpReleaseFence) {
- if (tmpError != mapper2::Error::NONE) {
- ALOGE("Failed to unlock buffer %p", buffer);
- }
-
- auto fenceHandle = tmpReleaseFence.getNativeHandle();
- if (fenceHandle) {
- if (fenceHandle->numInts != 0) {
- ALOGE("Invalid fence handle %p", fenceHandle);
- }
- if (fenceHandle->numFds == 1) {
- releaseFence = dup(fenceHandle->data[0]);
- if (releaseFence < 0) {
- ALOGE("Failed to dup fence fd");
- }
- } else {
- if (fenceHandle->numFds != 0) {
- ALOGE("Invalid fence handle %p", fenceHandle);
- }
- }
+template <typename AllocatorT, typename MapperT>
+void GrallocHalWrapper<AllocatorT, MapperT>::unlock(native_handle_t* bufferHandle) {
+ mMapper->unlock(bufferHandle, [&](auto error, const hidl_handle& /*releaseFence*/) {
+ if (failed(error)) {
+ ALOGE("Failed to unlock buffer %p: %" PRId32, bufferHandle,
+ static_cast<int32_t>(error));
}
});
+}
- return releaseFence;
+} // anonymous namespace
+
+GrallocWrapper::GrallocWrapper() {
+ sp<IAllocator3> allocator3 = IAllocator3::getService();
+ sp<IMapper3> mapper3 = IMapper3::getService();
+
+ if (allocator3 != nullptr && mapper3 != nullptr) {
+ mGrallocHal = std::unique_ptr<IGrallocHalWrapper>(
+ new GrallocHalWrapper<IAllocator3, IMapper3>(allocator3, mapper3));
+ } else {
+ ALOGD("Graphics HALs 3.0 not found (allocator %d mapper %d), falling back to 2.x",
+ (allocator3 != nullptr), (mapper3 != nullptr));
+
+ sp<IAllocator2> allocator2 = IAllocator2::getService();
+ sp<IMapper2> mapper2 = IMapper2_1::getService();
+ if (mapper2 == nullptr) {
+ mapper2 = IMapper2::getService();
+ }
+
+ if (allocator2 != nullptr && mapper2 != nullptr) {
+ mGrallocHal = std::unique_ptr<IGrallocHalWrapper>(
+ new GrallocHalWrapper<IAllocator2, IMapper2>(allocator2, mapper2));
+ } else {
+ ALOGE("Couldn't open 2.x/3.0 graphics HALs (2.x allocator %d mapper %d)",
+ (allocator2 != nullptr), (mapper2 != nullptr));
+ }
+ }
+}
+
+GrallocWrapper::~GrallocWrapper() {
+ for (auto bufferHandle : mAllocatedBuffers) {
+ mGrallocHal->unlock(bufferHandle);
+ mGrallocHal->freeBuffer(bufferHandle);
+ }
+ mAllocatedBuffers.clear();
+}
+
+std::string GrallocWrapper::dumpDebugInfo() {
+ return mGrallocHal->dumpDebugInfo();
+}
+
+std::pair<native_handle_t*, void*> GrallocWrapper::allocate(uint32_t size) {
+ native_handle_t* bufferHandle = mGrallocHal->allocate(size);
+ void* buffer = nullptr;
+ if (bufferHandle) {
+ buffer = mGrallocHal->lock(bufferHandle);
+ if (buffer) {
+ mAllocatedBuffers.insert(bufferHandle);
+ } else {
+ mGrallocHal->freeBuffer(bufferHandle);
+ bufferHandle = nullptr;
+ }
+ }
+ return std::make_pair<>(bufferHandle, buffer);
+}
+
+void GrallocWrapper::freeBuffer(native_handle_t* bufferHandle) {
+ if (mAllocatedBuffers.erase(bufferHandle)) {
+ mGrallocHal->unlock(bufferHandle);
+ mGrallocHal->freeBuffer(bufferHandle);
+ }
}
} // namespace android
diff --git a/sensors/common/vts/utils/SensorsHidlEnvironmentBase.cpp b/sensors/common/vts/utils/SensorsHidlEnvironmentBase.cpp
index affdf8b..fa0e2e9 100644
--- a/sensors/common/vts/utils/SensorsHidlEnvironmentBase.cpp
+++ b/sensors/common/vts/utils/SensorsHidlEnvironmentBase.cpp
@@ -29,7 +29,9 @@
void SensorsHidlEnvironmentBase::HidlTearDown() {
mStopThread = true;
- mPollThread.detach();
+ if (mPollThread.joinable()) {
+ mPollThread.detach();
+ }
}
void SensorsHidlEnvironmentBase::catEvents(std::vector<Event>* output) {
diff --git a/sensors/common/vts/utils/SensorsTestSharedMemory.cpp b/sensors/common/vts/utils/SensorsTestSharedMemory.cpp
index 819e297..3b068bd 100644
--- a/sensors/common/vts/utils/SensorsTestSharedMemory.cpp
+++ b/sensors/common/vts/utils/SensorsTestSharedMemory.cpp
@@ -119,32 +119,13 @@
}
case SharedMemType::GRALLOC: {
mGrallocWrapper = std::make_unique<::android::GrallocWrapper>();
- if (mGrallocWrapper->getAllocator() == nullptr ||
- mGrallocWrapper->getMapper() == nullptr) {
+ if (!mGrallocWrapper->isInitialized()) {
break;
}
- using android::hardware::graphics::common::V1_0::BufferUsage;
- using android::hardware::graphics::common::V1_0::PixelFormat;
- mapper2::IMapper::BufferDescriptorInfo buf_desc_info = {
- .width = static_cast<uint32_t>(size),
- .height = 1,
- .layerCount = 1,
- .usage = static_cast<uint64_t>(BufferUsage::SENSOR_DIRECT_DATA |
- BufferUsage::CPU_READ_OFTEN),
- .format = PixelFormat::BLOB};
- handle = const_cast<native_handle_t*>(mGrallocWrapper->allocate(buf_desc_info));
- if (handle != nullptr) {
- mapper2::IMapper::Rect region{0, 0, static_cast<int32_t>(buf_desc_info.width),
- static_cast<int32_t>(buf_desc_info.height)};
- buffer = static_cast<char*>(
- mGrallocWrapper->lock(handle, buf_desc_info.usage, region, /*fence=*/-1));
- if (buffer != nullptr) {
- break;
- }
- mGrallocWrapper->freeBuffer(handle);
- handle = nullptr;
- }
+ std::pair<native_handle_t*, void*> buf = mGrallocWrapper->allocate(size);
+ handle = buf.first;
+ buffer = static_cast<char*>(buf.second);
break;
}
default:
@@ -175,9 +156,7 @@
}
case SharedMemType::GRALLOC: {
if (mSize != 0) {
- mGrallocWrapper->unlock(mNativeHandle);
mGrallocWrapper->freeBuffer(mNativeHandle);
-
mNativeHandle = nullptr;
mSize = 0;
}
diff --git a/sensors/common/vts/utils/include/sensors-vts-utils/GrallocWrapper.h b/sensors/common/vts/utils/include/sensors-vts-utils/GrallocWrapper.h
index 3bd73c3..41e6334 100644
--- a/sensors/common/vts/utils/include/sensors-vts-utils/GrallocWrapper.h
+++ b/sensors/common/vts/utils/include/sensors-vts-utils/GrallocWrapper.h
@@ -14,66 +14,47 @@
* limitations under the License.
*/
-#ifndef GRALLO_WRAPPER_H_
-#define GRALLO_WRAPPER_H_
+#pragma once
+#include <utils/NativeHandle.h>
+
+#include <memory>
+#include <string>
#include <unordered_set>
-
-#include <android/hardware/graphics/allocator/2.0/IAllocator.h>
-#include <android/hardware/graphics/mapper/2.0/IMapper.h>
-
-namespace allocator2 = ::android::hardware::graphics::allocator::V2_0;
-namespace mapper2 = ::android::hardware::graphics::mapper::V2_0;
+#include <utility>
namespace android {
-// Modified from hardware/interfaces/graphics/mapper/2.0/vts/functional/
+class IGrallocHalWrapper;
+
+// Reference: hardware/interfaces/graphics/mapper/2.0/vts/functional/
class GrallocWrapper {
public:
GrallocWrapper();
~GrallocWrapper();
- sp<allocator2::IAllocator> getAllocator() const;
- sp<mapper2::IMapper> getMapper() const;
+ // After constructing this object, this function must be called to check the result. If it
+ // returns false, other methods are not safe to call.
+ bool isInitialized() const { return (mGrallocHal != nullptr); };
std::string dumpDebugInfo();
- // When import is false, this simply calls IAllocator::allocate. When import
- // is true, the returned buffers are also imported into the mapper.
- //
- // Either case, the returned buffers must be freed with freeBuffer.
- std::vector<const native_handle_t*> allocate(const mapper2::BufferDescriptor& descriptor,
- uint32_t count, bool import = true,
- uint32_t* outStride = nullptr);
- const native_handle_t* allocate(const mapper2::IMapper::BufferDescriptorInfo& descriptorInfo,
- bool import = true, uint32_t* outStride = nullptr);
+ // Allocates a gralloc buffer suitable for direct channel sensors usage with the given size.
+ // The buffer should be freed using freeBuffer when it's not needed anymore; otherwise it'll
+ // be freed when this object is destroyed.
+ // Returns a handle to the buffer, and a CPU-accessible pointer for reading. On failure, both
+ // will be set to nullptr.
+ std::pair<native_handle_t*, void*> allocate(uint32_t size);
- mapper2::BufferDescriptor createDescriptor(
- const mapper2::IMapper::BufferDescriptorInfo& descriptorInfo);
+ // Releases a gralloc buffer previously returned by allocate()
+ void freeBuffer(native_handle_t* bufferHandle);
- const native_handle_t* importBuffer(const hardware::hidl_handle& rawHandle);
- void freeBuffer(const native_handle_t* bufferHandle);
-
- // We use fd instead of hardware::hidl_handle in these functions to pass fences
- // in and out of the mapper. The ownership of the fd is always transferred
- // with each of these functions.
- void* lock(const native_handle_t* bufferHandle, uint64_t cpuUsage,
- const mapper2::IMapper::Rect& accessRegion, int acquireFence);
-
- int unlock(const native_handle_t* bufferHandle);
-
- private:
- void init();
- const native_handle_t* cloneBuffer(const hardware::hidl_handle& rawHandle);
-
- sp<allocator2::IAllocator> mAllocator;
- sp<mapper2::IMapper> mMapper;
+ private:
+ std::unique_ptr<IGrallocHalWrapper> mGrallocHal;
// Keep track of all cloned and imported handles. When a test fails with
// ASSERT_*, the destructor will free the handles for the test.
- std::unordered_set<const native_handle_t*> mClonedBuffers;
- std::unordered_set<const native_handle_t*> mImportedBuffers;
+ std::unordered_set<native_handle_t*> mAllocatedBuffers;
};
} // namespace android
-#endif // GRALLO_WRAPPER_H_
diff --git a/wifi/hostapd/1.1/vts/functional/hostapd_hidl_test.cpp b/wifi/hostapd/1.1/vts/functional/hostapd_hidl_test.cpp
index 26a58b2..ffd4d97 100644
--- a/wifi/hostapd/1.1/vts/functional/hostapd_hidl_test.cpp
+++ b/wifi/hostapd/1.1/vts/functional/hostapd_hidl_test.cpp
@@ -56,6 +56,9 @@
protected:
std::string getPrimaryWlanIfaceName() {
std::array<char, PROPERTY_VALUE_MAX> buffer;
+ auto res = property_get("ro.vendor.wifi.sap.interface",
+ buffer.data(), nullptr);
+ if (res > 0) return buffer.data();
property_get("wifi.interface", buffer.data(), "wlan0");
return buffer.data();
}