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 7dedd7f0b9..6be30d34df 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 #include #include -#include +#include #include #include #include @@ -129,9 +129,9 @@ public: 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 ®istered) { for (const auto &instance : registered) { sp drmFactory = @@ -144,7 +144,7 @@ public: } ); - manager->listByInterface(ICryptoFactory::descriptor, + manager->listManifestByInterface(ICryptoFactory::descriptor, [&](const hidl_vec ®istered) { for (const auto &instance : registered) { sp cryptoFactory = diff --git a/gnss/1.1/vts/functional/gnss_hal_test.cpp b/gnss/1.1/vts/functional/gnss_hal_test.cpp index 381ac1d3af..f3b376e6bd 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 +#include + #include #include #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 @@ void GnssHalTest::StartAndCheckLocations(int count) { } } +bool GnssHalTest::IsGnssHalVersion_1_1() const { + using ::android::hidl::manager::V1_2::IServiceManager; + sp manager = ::android::hardware::defaultServiceManager1_2(); + + bool hasGnssHalVersion_1_1 = false; + manager->listManifestByInterface( + "android.hardware.gnss@1.1::IGnss", + [&hasGnssHalVersion_1_1](const hidl_vec& 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& registered) { + hasGnssHalVersion_2_0 = registered.size() != 0; + }); + + return hasGnssHalVersion_1_1 && !hasGnssHalVersion_2_0; +} + void GnssHalTest::notify() { std::unique_lock 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 64478b5b1c..84a9f846fc 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 @@ class GnssHalTest : public ::testing::VtsHalHidlTargetTestBase { */ 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 gnss_hal_; // GNSS HAL to call into sp 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 2d901f3301..ee236ba5d1 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 @@ TEST_F(GnssHalTest, SetupTeardownCreateCleanup) {} * 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 iGnssMeas = gnssMeasurement; - EXPECT_NE(iGnssMeas, nullptr); + sp iGnssMeas_1_1 = gnssMeasurement_1_1; + sp 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 @@ TEST_F(GnssHalTest, TestGnssMeasurementCallback) { * 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 @@ IGnssConfiguration::BlacklistedSource FindStrongFrequentNonGpsSource( * 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 @@ TEST_F(GnssHalTest, BlacklistIndividualSatellites) { * 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 a8e40ba250..ae36c50689 100644 --- a/gnss/2.0/vts/functional/VtsHalGnssV2_0TargetTest.cpp +++ b/gnss/2.0/vts/functional/VtsHalGnssV2_0TargetTest.cpp @@ -23,7 +23,6 @@ int main(int argc, char** argv) { ::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 a9f858cc9d..14ae43ce26 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 @@ GnssHalTest::GnssCallback::GnssCallback() name_cbq_("name"), capabilities_cbq_("capabilities"), location_cbq_("location"), - sv_info_cbq_("sv_info") {} + sv_info_list_cbq_("sv_info") {} Return GnssHalTest::GnssCallback::gnssSetSystemInfoCb( const IGnssCallback_1_0::GnssSystemInfo& info) { @@ -204,7 +204,7 @@ Return GnssHalTest::GnssCallback::gnssSvStatusCb(const IGnssCallback_1_0:: Return GnssHalTest::GnssCallback::gnssSvStatusCb_2_0( const hidl_vec& 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 05e37d33f7..90a7866082 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 #include +#include #include using android::hardware::hidl_vec; @@ -85,6 +86,14 @@ class GnssHalTest : public ::testing::VtsHalHidlTargetTestBase { */ 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& 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 @@ class GnssHalTest : public ::testing::VtsHalHidlTargetTestBase { CallbackQueue name_cbq_; CallbackQueue capabilities_cbq_; CallbackQueue location_cbq_; - CallbackQueue> sv_info_cbq_; + CallbackQueue> sv_info_list_cbq_; GnssCallback(); virtual ~GnssCallback() = default; @@ -264,6 +273,19 @@ bool GnssHalTest::CallbackQueue::retrieve(T& event, int timeout_seconds) { return true; } +template +int GnssHalTest::CallbackQueue::retrieve(list& 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 int GnssHalTest::CallbackQueue::size() const { std::unique_lock lock(mtx_); 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 155afd614b..39736cc250 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 IAGnssRil_1_0 = android::hardware::gnss::V1_0::IAGnssRil; 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 @@ TEST_F(GnssHalTest, TestGnssMeasurementFields) { // Verify ConstellationType is valid. ASSERT_TRUE(static_cast(measurement.constellation) >= - static_cast(GnssConstellationType::UNKNOWN) && + static_cast(GnssConstellationType_2_0::UNKNOWN) && static_cast(measurement.constellation) <= - static_cast(GnssConstellationType::IRNSS)); + static_cast(GnssConstellationType_2_0::IRNSS)); // Verify State is valid. ASSERT_TRUE( @@ -414,3 +414,423 @@ TEST_F(GnssHalTest, TestGnssBatchingExtension) { 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>& 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 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(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> 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 gnss_configuration_hal = gnss_configuration_hal_return; + ASSERT_NE(gnss_configuration_hal, nullptr); + + hidl_vec 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 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 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 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 gnss_configuration_hal = gnss_configuration_hal_return; + ASSERT_NE(gnss_configuration_hal, nullptr); + + hidl_vec 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 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 835d9b8d16..21caddb4bf 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 #include void RadioHidlTest_v1_2::SetUp() { @@ -154,25 +153,7 @@ void RadioHidlTest_v1_2::updateSimCardStatus() { } 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 d3012bbd71..a4953d7a70 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_F(RadioHidlTest_v1_4, setPreferredNetworkTypeBitmap) { /* * 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(); @@ -196,10 +201,17 @@ TEST_F(RadioHidlTest_v1_4, startNetworkScan) { 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})); } } @@ -225,8 +237,9 @@ TEST_F(RadioHidlTest_v1_4, startNetworkScan_InvalidArgument) { 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})); } } @@ -261,8 +274,9 @@ TEST_F(RadioHidlTest_v1_4, startNetworkScan_InvalidInterval1) { 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})); } } @@ -296,8 +310,9 @@ TEST_F(RadioHidlTest_v1_4, startNetworkScan_InvalidInterval2) { 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})); } } @@ -331,8 +346,9 @@ TEST_F(RadioHidlTest_v1_4, startNetworkScan_InvalidMaxSearchTime1) { 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})); } } @@ -366,8 +382,9 @@ TEST_F(RadioHidlTest_v1_4, startNetworkScan_InvalidMaxSearchTime2) { 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})); } } @@ -401,8 +418,9 @@ TEST_F(RadioHidlTest_v1_4, startNetworkScan_InvalidPeriodicity1) { 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})); } } @@ -436,8 +454,9 @@ TEST_F(RadioHidlTest_v1_4, startNetworkScan_InvalidPeriodicity2) { 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})); } } @@ -473,8 +492,10 @@ TEST_F(RadioHidlTest_v1_4, startNetworkScan_GoodRequest1) { 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})); } } @@ -512,8 +533,10 @@ TEST_F(RadioHidlTest_v1_4, startNetworkScan_GoodRequest2) { 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 d4c5f321de..7bb992bf23 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 @@ cc_test { ], 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 47308e13b9..5453ef6d0c 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 8e8413c6a2..4765fa2797 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 @@ cc_test { ], 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 0525bdc63b..03fcc174ef 100644 --- a/sensors/2.0/vts/functional/SensorsHidlEnvironmentV2_0.cpp +++ b/sensors/2.0/vts/functional/SensorsHidlEnvironmentV2_0.cpp @@ -38,6 +38,13 @@ constexpr typename std::underlying_type::type asBaseType(EnumType valu 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 onDynamicSensorsConnected(const hidl_vec& /* sensorInfos */) { return Return(); @@ -56,6 +63,7 @@ bool SensorsHidlEnvironmentV2_0::resetHal() { if (mSensors == nullptr) { break; } + mSensors->linkToDeath(mDeathRecipient, 0 /* cookie */); // Initialize FMQs mEventQueue = std::make_unique(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 5e54530917..b0dbd90b05 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::sp; 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; @@ -83,6 +90,11 @@ class SensorsHidlEnvironmentV2_0 : public SensorsHidlEnvironmentBase { */ sp mSensors; + /** + * Monitors the HAL for crashes, triggering test failure if seen + */ + sp mDeathRecipient = new SensorsHalDeathRecipient(); + /** * Type used to simplify the creation of the Event FMQ */ diff --git a/sensors/2.0/vts/functional/VtsHalSensorsV2_0TargetTest.cpp b/sensors/2.0/vts/functional/VtsHalSensorsV2_0TargetTest.cpp index 62c5334441..8364ba992e 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::SensorsEventFormatOffset; 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(SensorsEventFormatOffset::TOTAL_LENGTH); @@ -69,9 +71,9 @@ class EventCallback : public IEventCallback { } void waitForFlushEvents(const std::vector& sensorsToWaitFor, - int32_t numCallsToFlush, int64_t timeoutMs) { + int32_t numCallsToFlush, milliseconds timeout) { std::unique_lock lock(mFlushMutex); - mFlushCV.wait_for(lock, std::chrono::milliseconds(timeoutMs), + mFlushCV.wait_for(lock, timeout, [&] { return flushesReceived(sensorsToWaitFor, numCallsToFlush); }); } @@ -80,10 +82,9 @@ class EventCallback : public IEventCallback { return mEventMap[sensorHandle]; } - void waitForEvents(const std::vector& sensorsToWaitFor, int32_t timeoutMs) { + void waitForEvents(const std::vector& sensorsToWaitFor, milliseconds timeout) { std::unique_lock 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 @@ class EventCallback : public IEventCallback { // 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 getSensorsList(); // implementation wrapper @@ -169,19 +176,21 @@ class SensorsHidlTest : public SensorsHidlTestBase { // Helper functions void activateAllSensors(bool enable); std::vector getNonOneShotSensors(); + std::vector getNonOneShotAndNonSpecialSensors(); std::vector getOneShotSensors(); std::vector 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 mem, - int32_t* directChannelHandle); + void verifyRegisterDirectChannel(std::shared_ptr 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 SensorsHidlTest::activate(int32_t sensorHandle, bool enabled) { @@ -250,6 +259,18 @@ std::vector SensorsHidlTest::getNonOneShotSensors() { return sensors; } +std::vector SensorsHidlTest::getNonOneShotAndNonSpecialSensors() { + std::vector 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 SensorsHidlTest::getOneShotSensors() { std::vector sensors; for (const SensorInfo& info : getSensorsList()) { @@ -368,7 +389,7 @@ TEST_F(SensorsHidlTest, InjectSensorEventData) { } // 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 @@ TEST_F(SensorsHidlTest, CallInitializeTwice) { std::unique_ptr newEnv = std::make_unique(); 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 @@ TEST_F(SensorsHidlTest, CallInitializeTwice) { 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 @@ TEST_F(SensorsHidlTest, CleanupConnectionsOnInitialize) { // 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 @@ void SensorsHidlTest::runFlushTest(const std::vector& sensors, bool } // 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 @@ TEST_F(SensorsHidlTest, Batch) { 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, Activate) { } 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 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 sensors = getNonOneShotAndNonSpecialSensors(); + milliseconds maxMinDelay(0); + for (const SensorInfo& sensor : sensors) { + milliseconds minDelay = duration_cast(microseconds(sensor.minDelay)); + maxMinDelay = milliseconds(std::max(maxMinDelay.count(), minDelay.count())); } // Activate the sensors so that they start generating events @@ -826,33 +863,46 @@ TEST_F(SensorsHidlTest, NoStaleEvents) { // 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 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(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( + nanoseconds(newEvent.timestamp - lastEventTimestampMap[sensor.sensorHandle])); + milliseconds sensorMinDelay = duration_cast(microseconds(sensor.minDelay)); + ASSERT_GE(delta, kFiveHundredMs + (3 * sensorMinDelay)); } - - getEnvironment()->unregisterCallback(); } void SensorsHidlTest::checkRateLevel(const SensorInfo& sensor, int32_t directChannelHandle, @@ -861,21 +911,43 @@ void SensorsHidlTest::checkRateLevel(const SensorInfo& sensor, int32_t directCha [&](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 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 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 @@ void SensorsHidlTest::verifyRegisterDirectChannel(const SensorInfo& sensor, Shar 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::verifyRegisterDirectChannel(const SensorInfo& sensor, Shar } 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 @@ void SensorsHidlTest::verifyConfigure(const SensorInfo& sensor, SharedMemType me -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 @@ void SensorsHidlTest::verifyDirectChannel(SharedMemType memType) { 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 @@ TEST_F(SensorsHidlTest, CleanupDirectConnectionOnInitialize) { // 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 95df4259e7..02dc608858 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 @@ cc_library_static { ], 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 7bed16d6c4..1cad9135b7 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 +#include +#include +#include +#include + #include +#include +#include + +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(bufferHandle); - native_handle_close(buffer); - native_handle_delete(buffer); - } - mClonedBuffers.clear(); - - for (auto bufferHandle : mImportedBuffers) { - auto buffer = const_cast(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 +class GrallocHalWrapper : public IGrallocHalWrapper { + public: + GrallocHalWrapper(const sp& allocator, const sp& mapper) + : mAllocator(allocator), mMapper(mapper) { + if (mapper->isRemote()) { + ALOGE("Mapper is in passthrough mode"); } } - mImportedBuffers.clear(); -} -sp 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(BufferUsage::SENSOR_DIRECT_DATA | BufferUsage::CPU_READ_OFTEN); + sp mAllocator; + sp mMapper; + + BufferDescriptor getDescriptor(uint32_t size); + native_handle_t* importBuffer(const hidl_handle& rawHandle); +}; + +template +std::string GrallocHalWrapper::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 +native_handle_t* GrallocHalWrapper::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& buffers) { + if (failed(error)) { + ALOGE("Failed to allocate buffer: %" PRId32, static_cast(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 GrallocWrapper::allocate( - const mapper2::BufferDescriptor& descriptor, uint32_t count, bool import, uint32_t* outStride) { - std::vector 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 +void GrallocHalWrapper::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 +BufferDescriptor GrallocHalWrapper::getDescriptor(uint32_t size) { + typename MapperT::BufferDescriptorInfo descriptorInfo = { + .width = size, + .height = 1, + .layerCount = 1, + .usage = kBufferUsage, + .format = static_cast(PixelFormat::BLOB), + }; -sp 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(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(tmpBuffer); - }); +template +native_handle_t* GrallocHalWrapper::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(error)); + } else { + bufferHandle = static_cast(tmpBuffer); + } + }); return bufferHandle; } -void GrallocWrapper::freeBuffer(const native_handle_t* bufferHandle) { - auto buffer = const_cast(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(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 +void* GrallocHalWrapper::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(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(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 +void GrallocHalWrapper::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(error)); } }); +} - return releaseFence; +} // anonymous namespace + +GrallocWrapper::GrallocWrapper() { + sp allocator3 = IAllocator3::getService(); + sp mapper3 = IMapper3::getService(); + + if (allocator3 != nullptr && mapper3 != nullptr) { + mGrallocHal = std::unique_ptr( + new GrallocHalWrapper(allocator3, mapper3)); + } else { + ALOGD("Graphics HALs 3.0 not found (allocator %d mapper %d), falling back to 2.x", + (allocator3 != nullptr), (mapper3 != nullptr)); + + sp allocator2 = IAllocator2::getService(); + sp mapper2 = IMapper2_1::getService(); + if (mapper2 == nullptr) { + mapper2 = IMapper2::getService(); + } + + if (allocator2 != nullptr && mapper2 != nullptr) { + mGrallocHal = std::unique_ptr( + new GrallocHalWrapper(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 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 affdf8b6b3..fa0e2e9bf0 100644 --- a/sensors/common/vts/utils/SensorsHidlEnvironmentBase.cpp +++ b/sensors/common/vts/utils/SensorsHidlEnvironmentBase.cpp @@ -29,7 +29,9 @@ void SensorsHidlEnvironmentBase::HidlSetUp() { void SensorsHidlEnvironmentBase::HidlTearDown() { mStopThread = true; - mPollThread.detach(); + if (mPollThread.joinable()) { + mPollThread.detach(); + } } void SensorsHidlEnvironmentBase::catEvents(std::vector* output) { diff --git a/sensors/common/vts/utils/SensorsTestSharedMemory.cpp b/sensors/common/vts/utils/SensorsTestSharedMemory.cpp index 819e2974f7..3b068bd5c5 100644 --- a/sensors/common/vts/utils/SensorsTestSharedMemory.cpp +++ b/sensors/common/vts/utils/SensorsTestSharedMemory.cpp @@ -119,32 +119,13 @@ SensorsTestSharedMemory::SensorsTestSharedMemory(SharedMemType type, size_t size } 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(size), - .height = 1, - .layerCount = 1, - .usage = static_cast(BufferUsage::SENSOR_DIRECT_DATA | - BufferUsage::CPU_READ_OFTEN), - .format = PixelFormat::BLOB}; - handle = const_cast(mGrallocWrapper->allocate(buf_desc_info)); - if (handle != nullptr) { - mapper2::IMapper::Rect region{0, 0, static_cast(buf_desc_info.width), - static_cast(buf_desc_info.height)}; - buffer = static_cast( - mGrallocWrapper->lock(handle, buf_desc_info.usage, region, /*fence=*/-1)); - if (buffer != nullptr) { - break; - } - mGrallocWrapper->freeBuffer(handle); - handle = nullptr; - } + std::pair buf = mGrallocWrapper->allocate(size); + handle = buf.first; + buffer = static_cast(buf.second); break; } default: @@ -175,9 +156,7 @@ SensorsTestSharedMemory::~SensorsTestSharedMemory() { } 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 3bd73c36e0..41e6334893 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 + +#include +#include #include - -#include -#include - -namespace allocator2 = ::android::hardware::graphics::allocator::V2_0; -namespace mapper2 = ::android::hardware::graphics::mapper::V2_0; +#include 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 getAllocator() const; - sp 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 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 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 mAllocator; - sp mMapper; + private: + std::unique_ptr 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 mClonedBuffers; - std::unordered_set mImportedBuffers; + std::unordered_set 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 26a58b2c61..ffd4d97a56 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 @@ class HostapdHidlTest : public ::testing::VtsHalHidlTargetTestBase { protected: std::string getPrimaryWlanIfaceName() { std::array 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(); }