assemble_vintf: build and fuse compatibility matrix at build time.
The fused matrix:
(1) has all requirements in compatibilility_matrix.V.xml, where V
is the "level" attribute in device manifest (or is inferred if missing)
(2) has all other HALs as optional HALs in compatibility_matrix.U.xml
files, where U > V, including current.xml.
Bug: 69636193
Test: m (system_)compatibility_matrix/manifest.xml
Test: libvintf_test
Change-Id: I01d2f1ea779e270a9b3ca8de63a064747f36eb2d
Merged-In: I01d2f1ea779e270a9b3ca8de63a064747f36eb2d
diff --git a/CompatibilityMatrix.cpp b/CompatibilityMatrix.cpp
index f788569..521c44b 100644
--- a/CompatibilityMatrix.cpp
+++ b/CompatibilityMatrix.cpp
@@ -16,6 +16,8 @@
#include "CompatibilityMatrix.h"
+#include <utility>
+
#include "parse_string.h"
#include "utils.h"
@@ -71,6 +73,63 @@
return "";
}
+static VersionRange* findRangeWithMajorVersion(std::vector<VersionRange>& versionRanges,
+ size_t majorVer) {
+ for (VersionRange& vr : versionRanges) {
+ if (vr.majorVer == majorVer) {
+ return &vr;
+ }
+ }
+ return nullptr;
+}
+
+std::pair<MatrixHal*, VersionRange*> CompatibilityMatrix::getHalWithMajorVersion(
+ const std::string& name, size_t majorVer) {
+ for (MatrixHal* hal : getHals(name)) {
+ VersionRange* vr = findRangeWithMajorVersion(hal->versionRanges, majorVer);
+ if (vr != nullptr) {
+ return {hal, vr};
+ }
+ }
+ return {nullptr, nullptr};
+}
+
+bool CompatibilityMatrix::addAllHalsAsOptional(CompatibilityMatrix* other, std::string* error) {
+ if (other == nullptr || other->level() <= level()) {
+ return true;
+ }
+
+ for (auto& pair : other->mHals) {
+ const std::string& name = pair.first;
+ MatrixHal& halToAdd = pair.second;
+ for (const VersionRange& vr : halToAdd.versionRanges) {
+ MatrixHal* existingHal;
+ VersionRange* existingVr;
+ std::tie(existingHal, existingVr) = getHalWithMajorVersion(name, vr.majorVer);
+
+ if (existingHal == nullptr) {
+ halToAdd.optional = true;
+ add(std::move(halToAdd));
+ continue;
+ }
+
+ if (!existingHal->optional && !existingHal->containsInstances(halToAdd)) {
+ if (error != nullptr) {
+ *error = "HAL " + name + "@" + to_string(vr.minVer()) + " is a required " +
+ "HAL, but fully qualified instance names don't match (at FCM "
+ "Version " +
+ std::to_string(level()) + " and " + std::to_string(other->level()) +
+ ")";
+ }
+ return false;
+ }
+
+ existingVr->maxMinor = std::max(existingVr->maxMinor, vr.maxMinor);
+ }
+ }
+ return true;
+}
+
bool operator==(const CompatibilityMatrix &lft, const CompatibilityMatrix &rgt) {
return lft.mType == rgt.mType && lft.mLevel == rgt.mLevel && lft.mHals == rgt.mHals &&
lft.mXmlFiles == rgt.mXmlFiles &&