diff options
author | Yifan Hong <elsk@google.com> | 2023-03-09 16:37:17 -0800 |
---|---|---|
committer | Yifan Hong <elsk@google.com> | 2023-03-09 17:57:28 -0800 |
commit | 2bec0220cf4502ab9c3bf21b977389a0aa96efcf (patch) | |
tree | 8d33b6d32779fed89210c6f14f08fb163e716820 | |
parent | 86d403c0b275d915023ed7171383d3c9c6890a36 (diff) | |
download | hal-2bec0220cf4502ab9c3bf21b977389a0aa96efcf.tar.gz |
Treble VINTF test: Allow vendor extensions for passthrough HALs.
The change cc24ca47869880b25f33288469cc2ea3674bbaf7
"Treble VINTF test: parameterize on HAL instances."
https://android.googlesource.com/platform/test/vts-testcase/hal/+/cc24ca47869880b25f33288469cc2ea3674bbaf7
accidentally introduced a requirement on passhthrough
vendor extension HALs that the dynamic library (.so)
with the name of the vendor extension must exist. For example,
if vendor.foo.display.mapper extends android.hardware.graphics.mapper,
it was erroneously required that vendor.foo.display.mapper@3.0-impl.so
exists. This was because when the test cannot find
vendor.foo.display.mapper@3.0-impl.so, it skips calling interfaceChain
on it, thus it cannot infer that it extends a HAL that is in
the passthrough allowlist.
Remove this incorrectly imposed requirement by actually searching for
all passthrough HALs on the device and look for the implementation
that also implements vendor.foo.display.mapper@3.0. Then, look up
intefaceChain() on the implementation to match against the allowlist.
Bug: 261765512
Test: vts_treble_vintf_vendor_test --gtest_filter=*vendor* on a pixel
device
Change-Id: I06bc822e3af82ad5c7ca53207a10175610779b51
-rw-r--r-- | treble/vintf/SingleManifestTest.cpp | 81 | ||||
-rw-r--r-- | treble/vintf/SingleManifestTest.h | 4 |
2 files changed, 83 insertions, 2 deletions
diff --git a/treble/vintf/SingleManifestTest.cpp b/treble/vintf/SingleManifestTest.cpp index 14778912..0cfedfee 100644 --- a/treble/vintf/SingleManifestTest.cpp +++ b/treble/vintf/SingleManifestTest.cpp @@ -106,7 +106,8 @@ static FqInstance ToFqInstance(const string &interface, // Given android.foo.bar@x.y::IFoo/default, attempt to get // android.foo.bar@x.y::IFoo/default, android.foo.bar@x.(y-1)::IFoo/default, // ... android.foo.bar@x.0::IFoo/default until the passthrough HAL is retrieved. -static sp<IBase> GetPassthroughService(const FqInstance &fq_instance) { +static sp<IBase> GetPassthroughServiceExact(const FqInstance &fq_instance, + bool expect_interface_chain_valid) { for (size_t minor_version = fq_instance.getMinorVersion();; --minor_version) { // String out instance name from fq_instance. FqInstance interface; @@ -131,7 +132,7 @@ static sp<IBase> GetPassthroughService(const FqInstance &fq_instance) { } } }); - if (!interface_chain_valid) { + if (!interface_chain_valid && expect_interface_chain_valid) { ADD_FAILURE() << "Retrieved " << interface.string() << "/" << fq_instance.getInstance() << " as " << fq_instance.string() @@ -153,6 +154,82 @@ static sp<IBase> GetPassthroughService(const FqInstance &fq_instance) { return nullptr; } +// Given vendor.foo.bar@x.y::IFoo/default, also look up all declared passthrough +// HAL implementations on the device that implements this interface. +sp<IBase> SingleHidlTest::GetPassthroughService(const FqInstance &fq_instance) { + sp<IBase> hal_service = GetPassthroughServiceExact( + fq_instance, true /* expect_interface_chain_valid */); + if (hal_service != nullptr) { + return hal_service; + } + + // For vendor extensions, hal_service may be null because we don't know + // its interfaceChain()[1] to call getService(). However, the base interface + // should be declared in the manifest. Attempt to find it. + cout + << "Can't find passthrough service " << fq_instance.string() + << ". It might be a vendor extension. Searching all passthrough services " + "on the device for a match." + << endl; + + const auto &[_, manifest] = GetParam(); + auto all_declared_passthrough_instances = GetHidlInstances(manifest); + for (const HidlInstance &other_hidl_instance : + all_declared_passthrough_instances) { + if (other_hidl_instance.transport() != Transport::PASSTHROUGH) { + continue; + } + if (other_hidl_instance.instance_name() != fq_instance.getInstance()) { + cout << "Skipping " << other_hidl_instance.fq_name().string() << "/" + << other_hidl_instance.instance_name() + << " because instance name is not " << fq_instance.getInstance(); + continue; + } + auto other_fq_instance = FqInstance::from( + other_hidl_instance.fq_name(), other_hidl_instance.instance_name()); + if (!other_fq_instance) { + cout << other_hidl_instance.fq_name().string() << "/" + << other_hidl_instance.instance_name() + << " is not a valid FqInstance, skipping." << endl; + continue; + } + auto other_service = GetPassthroughServiceExact( + *other_fq_instance, false /* expect_interface_chain_valid */); + if (other_service == nullptr) { + cout << "Cannot retrieve " << other_fq_instance->string() << ", skipping." + << endl; + continue; + } + bool match = false; + auto other_interface_chain_ret = + other_service->interfaceChain([&](const auto &chain) { + for (const auto &intf : chain) { + auto other_fq_instance_in_chain = FqInstance::from( + std::string(intf) + "/" + other_fq_instance->getInstance()); + if (other_fq_instance_in_chain == fq_instance) { + match = true; + break; + } + } + }); + if (!other_interface_chain_ret.isOk()) { + cout << "Cannot call interfaceChain on " << other_fq_instance->string() + << ", skipping." << endl; + continue; + } + if (match) { + cout << "The implementation of " << other_fq_instance->string() + << " also implements " << fq_instance.string() + << ", using it to check if passthrough is allowed for " + << fq_instance.string() << endl; + return other_service; + } + } + cout << "Can't find any other passthrough service implementing " + << fq_instance.string() << endl; + return nullptr; +} + // returns true only if the specified apex is updated static bool IsApexUpdated(const std::string &apex_name) { using namespace ::android::apex; diff --git a/treble/vintf/SingleManifestTest.h b/treble/vintf/SingleManifestTest.h index 22003073..09967f3b 100644 --- a/treble/vintf/SingleManifestTest.h +++ b/treble/vintf/SingleManifestTest.h @@ -17,6 +17,8 @@ #ifndef VTS_TREBLE_VINTF_TEST_SINGLE_MANIFEST_TEST_H_ #define VTS_TREBLE_VINTF_TEST_SINGLE_MANIFEST_TEST_H_ #include <gtest/gtest.h> +#include <hidl-util/FqInstance.h> + #include "VtsTrebleVintfTestBase.h" namespace android { @@ -30,6 +32,8 @@ class SingleHidlTest : public VtsTrebleVintfTestBase, std::tuple<HidlInstance, HalManifestPtr>> { public: virtual ~SingleHidlTest() {} + + sp<IBase> GetPassthroughService(const android::FqInstance& fq_instance); }; // A parameterized test for an HIDL HAL registered through hwservicemanager |