servicemanager: check VINTF manifest for VINTF ifs
For interfaces that are exported API to vendor, check that the
interfaces are declared in the manifest before allowing them to
register.
Implements this relationship:
Device using VINTF instance => instance in manifest
The manifest is used for two things:
- understand which HAL interfaces are used so that we don't deprecate
them too early.
- understand which interfaces are on the device: this allows clients to
depend on a HAL interface IFF it is installed.
Bug: 136027762
Test: try registering interface that is and isn't in the VINTF manifest
Change-Id: I8aa09a56c638a6cc3aa93f102caf09da401a143b
diff --git a/cmds/servicemanager/Android.bp b/cmds/servicemanager/Android.bp
index 9cf3c5c..7277e85 100644
--- a/cmds/servicemanager/Android.bp
+++ b/cmds/servicemanager/Android.bp
@@ -15,11 +15,18 @@
shared_libs: [
"libbase",
"libbinder", // also contains servicemanager_interface
+ "libvintf",
"libcutils",
"liblog",
"libutils",
"libselinux",
],
+
+ target: {
+ vendor: {
+ exclude_shared_libs: ["libvintf"],
+ },
+ },
}
cc_binary {
diff --git a/cmds/servicemanager/ServiceManager.cpp b/cmds/servicemanager/ServiceManager.cpp
index 463d67f..9344368 100644
--- a/cmds/servicemanager/ServiceManager.cpp
+++ b/cmds/servicemanager/ServiceManager.cpp
@@ -18,14 +18,52 @@
#include <android-base/logging.h>
#include <android-base/properties.h>
+#include <binder/Stability.h>
#include <cutils/android_filesystem_config.h>
#include <cutils/multiuser.h>
#include <thread>
+#ifndef VENDORSERVICEMANAGER
+#include <vintf/VintfObject.h>
+#include <vintf/constants.h>
+#endif // !VENDORSERVICEMANAGER
+
using ::android::binder::Status;
+using ::android::internal::Stability;
namespace android {
+#ifndef VENDORSERVICEMANAGER
+static bool meetsDeclarationRequirements(const sp<IBinder>& binder, const std::string& name) {
+ if (!Stability::requiresVintfDeclaration(binder)) {
+ return true;
+ }
+
+ size_t firstSlash = name.find('/');
+ size_t lastDot = name.rfind('.', firstSlash);
+ if (firstSlash == std::string::npos || lastDot == std::string::npos) {
+ LOG(ERROR) << "VINTF HALs require names in the format type/instance (e.g. "
+ << "some.package.foo.IFoo/default) but got: " << name;
+ return false;
+ }
+ const std::string package = name.substr(0, lastDot);
+ const std::string iface = name.substr(lastDot+1, firstSlash-lastDot-1);
+ const std::string instance = name.substr(firstSlash+1);
+
+ for (const auto& manifest : {
+ vintf::VintfObject::GetDeviceHalManifest(),
+ vintf::VintfObject::GetFrameworkHalManifest()
+ }) {
+ if (manifest->hasAidlInstance(package, iface, instance)) {
+ return true;
+ }
+ }
+ LOG(ERROR) << "Could not find " << package << "." << iface << "/" << instance
+ << " in the VINTF manifest.";
+ return false;
+}
+#endif // !VENDORSERVICEMANAGER
+
ServiceManager::ServiceManager(std::unique_ptr<Access>&& access) : mAccess(std::move(access)) {}
ServiceManager::~ServiceManager() {
// this should only happen in tests
@@ -119,6 +157,13 @@
return Status::fromExceptionCode(Status::EX_ILLEGAL_ARGUMENT);
}
+#ifndef VENDORSERVICEMANAGER
+ if (!meetsDeclarationRequirements(binder, name)) {
+ // already logged
+ return Status::fromExceptionCode(Status::EX_ILLEGAL_ARGUMENT);
+ }
+#endif // !VENDORSERVICEMANAGER
+
// implicitly unlinked when the binder is removed
if (OK != binder->linkToDeath(this)) {
LOG(ERROR) << "Could not linkToDeath when adding " << name;