checkUnusedHals: use hidl metadata
Use libhidlmetadata to infer relationships between interfaces. For
example, if GNSS@2.0 is listed as "optional", but a manifest lists
GNSS@1.1 and 2.0 (because 2.0 inherits from 1.1), do not complain
about an unused 1.1 HAL.
Bug: 131717099
Test: drop GNSS 1.1 from matrix and `m check-vintf-all`
Change-Id: I1c0ef715bf64cacf99de590ed6627afa2b60f4b1
Merged-In: I1c0ef715bf64cacf99de590ed6627afa2b60f4b1
diff --git a/Android.bp b/Android.bp
index bfbd353..12ab161 100644
--- a/Android.bp
+++ b/Android.bp
@@ -63,6 +63,9 @@
"libtinyxml2",
"libz",
],
+ header_libs: [
+ "libhidlmetadata_headers",
+ ],
export_include_dirs: ["include", "."],
local_include_dirs: ["include/vintf"],
@@ -70,7 +73,9 @@
"libbase",
"libhidl-gen-utils",
],
-
+ export_header_lib_headers: [
+ "libhidlmetadata_headers",
+ ],
target: {
host: {
srcs: [
@@ -113,6 +118,7 @@
static_libs: [
"libbase",
"libhidl-gen-utils",
+ "libhidlmetadata",
"liblog",
"libvintf",
"libutils",
diff --git a/HalManifest.cpp b/HalManifest.cpp
index bd0379a..9118773 100644
--- a/HalManifest.cpp
+++ b/HalManifest.cpp
@@ -227,15 +227,44 @@
return ret;
}
-std::set<std::string> HalManifest::checkUnusedHals(const CompatibilityMatrix& mat) const {
+std::set<std::string> HalManifest::checkUnusedHals(
+ const CompatibilityMatrix& mat, const std::vector<HidlInterfaceMetadata>& hidlMetadata) const {
+ std::multimap<std::string, std::string> childrenMap;
+ for (const auto& child : hidlMetadata) {
+ for (const auto& parent : child.inherited) {
+ childrenMap.emplace(parent, child.name);
+ }
+ }
+
std::set<std::string> ret;
- forEachInstance([&ret, &mat](const auto& manifestInstance) {
- if (!mat.matchInstance(manifestInstance.format(), manifestInstance.package(),
- manifestInstance.version(), manifestInstance.interface(),
- manifestInstance.instance())) {
- ret.insert(manifestInstance.description());
+ forEachInstance([&ret, &mat, &childrenMap](const auto& manifestInstance) {
+ if (mat.matchInstance(manifestInstance.format(), manifestInstance.package(),
+ manifestInstance.version(), manifestInstance.interface(),
+ manifestInstance.instance())) {
+ // manifestInstance exactly matches an instance in |mat|.
+ return true;
}
+ // For HIDL instances, If foo@2.0 inherits from foo@1.0, manifest may contain both, but
+ // matrix may contain only 2.0 if 1.0 is considered deprecated. Hence, if manifestInstance
+ // is 1.0, check all its children in the matrix too.
+ // If there is at least one match, do not consider it unused.
+ if (manifestInstance.format() == HalFormat::HIDL) {
+ auto range =
+ childrenMap.equal_range(manifestInstance.getFqInstance().getFqName().string());
+ for (auto it = range.first; it != range.second; ++it) {
+ FQName fqName;
+ CHECK(fqName.setTo(it->second));
+ if (mat.matchInstance(manifestInstance.format(), fqName.package(),
+ fqName.getVersion(), fqName.name(),
+ manifestInstance.instance())) {
+ return true;
+ }
+ }
+ }
+
+ // If no match is found, consider it unused.
+ ret.insert(manifestInstance.description());
return true;
});
diff --git a/VintfObject.cpp b/VintfObject.cpp
index 4f47622..320f97f 100644
--- a/VintfObject.cpp
+++ b/VintfObject.cpp
@@ -25,6 +25,7 @@
#include <android-base/logging.h>
#include <android-base/result.h>
#include <android-base/strings.h>
+#include <hidl/metadata.h>
#include "CompatibilityMatrix.h"
#include "parse_string.h"
@@ -833,7 +834,8 @@
return false;
}
-android::base::Result<void> VintfObject::checkUnusedHals() {
+android::base::Result<void> VintfObject::checkUnusedHals(
+ const std::vector<HidlInterfaceMetadata>& hidlMetadata) {
auto matrix = getFrameworkCompatibilityMatrix();
if (matrix == nullptr) {
return android::base::Error(-NAME_NOT_FOUND) << "Missing framework matrix.";
@@ -842,7 +844,7 @@
if (manifest == nullptr) {
return android::base::Error(-NAME_NOT_FOUND) << "Missing device manifest.";
}
- auto unused = manifest->checkUnusedHals(*matrix);
+ auto unused = manifest->checkUnusedHals(*matrix, hidlMetadata);
if (!unused.empty()) {
return android::base::Error()
<< "The following instances are in the device manifest but "
diff --git a/check_vintf.cpp b/check_vintf.cpp
index f2a239a..c2a20a1 100644
--- a/check_vintf.cpp
+++ b/check_vintf.cpp
@@ -26,6 +26,7 @@
#include <android-base/parseint.h>
#include <android-base/result.h>
#include <android-base/strings.h>
+#include <hidl/metadata.h>
#include <utils/Errors.h>
#include <vintf/KernelConfigParser.h>
#include <vintf/VintfObject.h>
@@ -380,7 +381,8 @@
}
auto targetFcm = deviceManifest->level();
if (*hasFcmExt || (targetFcm != Level::UNSPECIFIED && targetFcm >= Level::R)) {
- return vintfObject->checkUnusedHals();
+ auto hidlMetadata = HidlInterfaceMetadata::all();
+ return vintfObject->checkUnusedHals(hidlMetadata);
}
LOG(INFO) << "Skip checking unused HALs.";
return {};
diff --git a/include/vintf/HalManifest.h b/include/vintf/HalManifest.h
index e7b2a0e..41298f0 100644
--- a/include/vintf/HalManifest.h
+++ b/include/vintf/HalManifest.h
@@ -24,6 +24,8 @@
#include <string>
#include <vector>
+#include <hidl/metadata.h>
+
#include "CheckFlags.h"
#include "FileSystem.h"
#include "HalGroup.h"
@@ -175,7 +177,9 @@
// required HAL.
// That is, return empty list iff
// (instance in manifest) => (instance in matrix).
- std::set<std::string> checkUnusedHals(const CompatibilityMatrix& mat) const;
+ std::set<std::string> checkUnusedHals(
+ const CompatibilityMatrix& mat,
+ const std::vector<HidlInterfaceMetadata>& hidlMetadata) const;
// Check that manifest has no entries.
bool empty() const;
diff --git a/include/vintf/VintfObject.h b/include/vintf/VintfObject.h
index 900a90a..2a40271 100644
--- a/include/vintf/VintfObject.h
+++ b/include/vintf/VintfObject.h
@@ -21,6 +21,7 @@
#include <optional>
#include <android-base/result.h>
+#include <hidl/metadata.h>
#include "CheckFlags.h"
#include "CompatibilityMatrix.h"
@@ -213,7 +214,8 @@
* - !result.ok() && result.error().code() != 0 if any error. Check
* result.error() for detailed message.
*/
- android::base::Result<void> checkUnusedHals();
+ android::base::Result<void> checkUnusedHals(
+ const std::vector<HidlInterfaceMetadata>& hidlMetadata);
private:
std::unique_ptr<FileSystem> mFileSystem;
diff --git a/test/LibVintfTest.cpp b/test/LibVintfTest.cpp
index c22220b..fac2306 100644
--- a/test/LibVintfTest.cpp
+++ b/test/LibVintfTest.cpp
@@ -125,7 +125,7 @@
return cm1->addAllXmlFilesAsOptional(cm2, e);
}
std::set<std::string> checkUnusedHals(const HalManifest& m, const CompatibilityMatrix& cm) {
- return m.checkUnusedHals(cm);
+ return m.checkUnusedHals(cm, {});
}
std::map<std::string, HalInterface> testHalInterfaces() {