summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorYifan Hong <elsk@google.com>2023-03-09 16:37:17 -0800
committerYifan Hong <elsk@google.com>2023-03-09 17:57:28 -0800
commit2bec0220cf4502ab9c3bf21b977389a0aa96efcf (patch)
tree8d33b6d32779fed89210c6f14f08fb163e716820
parent86d403c0b275d915023ed7171383d3c9c6890a36 (diff)
downloadhal-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.cpp81
-rw-r--r--treble/vintf/SingleManifestTest.h4
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