summaryrefslogtreecommitdiff
path: root/treble/vintf/SingleManifestTest.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'treble/vintf/SingleManifestTest.cpp')
-rw-r--r--treble/vintf/SingleManifestTest.cpp81
1 files changed, 79 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;