Check matrices have up-to-date minor versions and HALs
Bug: 110261831
Test: TH
Change-Id: Ic160896a22223b32cda875e575051eba3b71c85b
diff --git a/VintfObject.cpp b/VintfObject.cpp
index 71588af..5ec5505 100644
--- a/VintfObject.cpp
+++ b/VintfObject.cpp
@@ -23,12 +23,14 @@
#include <memory>
#include <mutex>
+#include <aidl/metadata.h>
#include <android-base/logging.h>
#include <android-base/result.h>
#include <android-base/strings.h>
#include <hidl/metadata.h>
#include "CompatibilityMatrix.h"
+#include "constants-private.h"
#include "parse_string.h"
#include "parse_xml.h"
#include "utils.h"
@@ -64,7 +66,7 @@
// lose the status.
LOG(ERROR) << id << ": status from fetching VINTF information: " << status;
LOG(ERROR) << id << ": " << status << " VINTF parse error: " << error;
- ptr->object = nullptr; // frees the old object
+ ptr->object = nullptr; // frees the old object
}
}
return ptr->object;
@@ -975,6 +977,130 @@
return {};
}
+namespace {
+
+// Insert |name| into |ret| if shouldCheck(name).
+void InsertIf(const std::string& name, const std::function<bool(const std::string&)>& shouldCheck,
+ std::set<std::string>* ret) {
+ if (shouldCheck(name)) ret->insert(name);
+}
+
+std::string StripHidlInterface(const std::string& fqNameString) {
+ FQName fqName;
+ if (!fqName.setTo(fqNameString)) {
+ return "";
+ }
+ return fqName.getPackageAndVersion().string();
+}
+
+std::string StripAidlType(const std::string& type) {
+ auto items = android::base::Split(type, ".");
+ if (items.empty()) {
+ return "";
+ }
+ items.erase(items.end() - 1);
+ return android::base::Join(items, ".");
+}
+
+std::set<std::string> HidlMetadataToSet(
+ const std::vector<HidlInterfaceMetadata>& hidlMetadata,
+ const std::function<bool(const std::string&)>& shouldCheck) {
+ std::set<std::string> ret;
+ for (const auto& item : hidlMetadata) {
+ InsertIf(StripHidlInterface(item.name), shouldCheck, &ret);
+ }
+ return ret;
+}
+
+std::set<std::string> AidlMetadataToSet(
+ const std::vector<AidlInterfaceMetadata>& aidlMetadata,
+ const std::function<bool(const std::string&)>& shouldCheck) {
+ std::set<std::string> ret;
+ for (const auto& item : aidlMetadata) {
+ for (const auto& type : item.types) {
+ InsertIf(StripAidlType(type), shouldCheck, &ret);
+ }
+ }
+ return ret;
+}
+
+} // anonymous namespace
+
+android::base::Result<void> VintfObject::checkMissingHalsInMatrices(
+ const std::vector<HidlInterfaceMetadata>& hidlMetadata,
+ const std::vector<AidlInterfaceMetadata>& aidlMetadata,
+ std::function<bool(const std::string&)> shouldCheck) {
+ if (!shouldCheck) {
+ shouldCheck = [](const auto&) { return true; };
+ }
+
+ // Get all framework matrix fragments instead of the combined framework compatibility matrix
+ // because the latter may omit interfaces from the latest FCM if device target-level is not
+ // the latest.
+ std::vector<CompatibilityMatrix> matrixFragments;
+ std::string error;
+ auto matrixFragmentsStatus = getAllFrameworkMatrixLevels(&matrixFragments, &error);
+ if (matrixFragmentsStatus != OK) {
+ return android::base::Error(-matrixFragmentsStatus)
+ << "Unable to get all framework matrix fragments: " << error;
+ }
+ if (matrixFragments.empty()) {
+ if (error.empty()) {
+ error = "Cannot get framework matrix for each FCM version for unknown error.";
+ }
+ return android::base::Error(-NAME_NOT_FOUND) << error;
+ }
+
+ // Filter aidlMetadata and hidlMetadata with shouldCheck.
+ auto allAidlInterfaces = AidlMetadataToSet(aidlMetadata, shouldCheck);
+ auto allHidlInterfaces = HidlMetadataToSet(hidlMetadata, shouldCheck);
+
+ // Filter out instances in allAidlMetadata and allHidlMetadata that are in the matrices.
+ std::vector<std::string> errors;
+ for (const auto& matrix : matrixFragments) {
+ matrix.forEachInstance([&](const MatrixInstance& matrixInstance) {
+ switch (matrixInstance.format()) {
+ case HalFormat::AIDL: {
+ allAidlInterfaces.erase(matrixInstance.package());
+ return true; // continue to next instance
+ }
+ case HalFormat::HIDL: {
+ for (Version v = matrixInstance.versionRange().minVer();
+ v <= matrixInstance.versionRange().maxVer(); ++v.minorVer) {
+ allHidlInterfaces.erase(toFQNameString(matrixInstance.package(), v));
+ }
+ return true; // continue to next instance
+ }
+ default: {
+ if (shouldCheck(matrixInstance.package())) {
+ errors.push_back("HAL package " + matrixInstance.package() +
+ " is not allowed to have format " +
+ to_string(matrixInstance.format()) + ".");
+ }
+ return true; // continue to next instance
+ }
+ }
+ });
+ }
+
+ if (!allHidlInterfaces.empty()) {
+ errors.push_back(
+ "The following HIDL packages are not found in any compatibility matrix fragments:\t\n" +
+ android::base::Join(allHidlInterfaces, "\t\n"));
+ }
+ if (!allAidlInterfaces.empty()) {
+ errors.push_back(
+ "The following AIDL packages are not found in any compatibility matrix fragments:\t\n" +
+ android::base::Join(allAidlInterfaces, "\t\n"));
+ }
+
+ 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())) {}
@@ -1003,5 +1129,5 @@
return std::move(mObject);
}
-} // namespace vintf
-} // namespace android
+} // namespace vintf
+} // namespace android