Add checkMatrixHalsHasDefinition

This function checks that all HALs in the FCM is defined in
lib*idlmetadata.

Bug: 179099519
Test: vintf_object_test
Test: m check-vintf-all

Change-Id: Ib20ae90cbfe0292f6aaf96566ce9b02a7dbf8491
diff --git a/VintfObject.cpp b/VintfObject.cpp
index 9d33c5d..59d8d30 100644
--- a/VintfObject.cpp
+++ b/VintfObject.cpp
@@ -1073,6 +1073,28 @@
     return ret;
 }
 
+// android.hardware.foo@1.0::IFoo.
+// Note that UDTs are not filtered out, so there might be non-interface types.
+std::set<std::string> HidlMetadataToNames(const std::vector<HidlInterfaceMetadata>& hidlMetadata) {
+    std::set<std::string> ret;
+    for (const auto& item : hidlMetadata) {
+        ret.insert(item.name);
+    }
+    return ret;
+}
+
+// android.hardware.foo.IFoo
+// Note that UDTs are not filtered out, so there might be non-interface types.
+std::set<std::string> AidlMetadataToNames(const std::vector<AidlInterfaceMetadata>& aidlMetadata) {
+    std::set<std::string> ret;
+    for (const auto& item : aidlMetadata) {
+        for (const auto& type : item.types) {
+            ret.insert(type);
+        }
+    }
+    return ret;
+}
+
 }  // anonymous namespace
 
 android::base::Result<std::vector<CompatibilityMatrix>> VintfObject::getAllFrameworkMatrixLevels() {
@@ -1157,6 +1179,68 @@
     return {};
 }
 
+android::base::Result<void> VintfObject::checkMatrixHalsHasDefinition(
+    const std::vector<HidlInterfaceMetadata>& hidlMetadata,
+    const std::vector<AidlInterfaceMetadata>& aidlMetadata) {
+    auto matrixFragments = getAllFrameworkMatrixLevels();
+    if (!matrixFragments.ok()) return matrixFragments.error();
+
+    auto allAidlNames = AidlMetadataToNames(aidlMetadata);
+    auto allHidlNames = HidlMetadataToNames(hidlMetadata);
+    std::set<std::string> badAidlInterfaces;
+    std::set<std::string> badHidlInterfaces;
+
+    std::vector<std::string> errors;
+    for (const auto& matrix : matrixFragments.value()) {
+        if (matrix.level() == Level::UNSPECIFIED) {
+            LOG(INFO) << "Skip checkMatrixHalsHasDefinition() on " << matrix.fileName()
+                      << " with no level.";
+            continue;
+        }
+
+        matrix.forEachInstance([&](const MatrixInstance& matrixInstance) {
+            switch (matrixInstance.format()) {
+                case HalFormat::AIDL: {
+                    auto matrixInterface =
+                        toAidlFqnameString(matrixInstance.package(), matrixInstance.interface());
+                    if (allAidlNames.find(matrixInterface) == allAidlNames.end()) {
+                        errors.push_back(
+                            "AIDL interface " + matrixInterface + " is referenced in " +
+                            matrix.fileName() +
+                            ", but there is no corresponding .aidl definition associated with an "
+                            "aidl_interface module in this build. Typo?");
+                    }
+                    return true;  // continue to next instance
+                }
+                case HalFormat::HIDL: {
+                    for (Version v = matrixInstance.versionRange().minVer();
+                         v <= matrixInstance.versionRange().maxVer(); ++v.minorVer) {
+                        auto matrixInterface = matrixInstance.interfaceDescription(v);
+                        if (allHidlNames.find(matrixInterface) == allHidlNames.end()) {
+                            errors.push_back(
+                                "HIDL interface " + matrixInterface + " is referenced in " +
+                                matrix.fileName() +
+                                ", but there is no corresponding .hal definition associated with "
+                                "a hidl_interface module in this build. Typo?");
+                        }
+                    }
+                    return true;  // continue to next instance
+                }
+                default: {
+                    // We do not have data for native HALs.
+                    return true;  // continue to next instance
+                }
+            }
+        });
+    }
+
+    if (!errors.empty()) {
+        return android::base::Error() << android::base::Join(errors, "\n");
+    }
+
+    return {};
+}
+
 // make_unique does not work because VintfObject constructor is private.
 VintfObject::Builder::Builder() : mObject(std::unique_ptr<VintfObject>(new VintfObject())) {}