regex-instance: Fix CompatibilityMatrix::combine to use regex API
combine() is used when a framework compatibility matrix is formed.
Fix it so that the generated FCM contains <regex-instance> as well.
Caveat: In the old code, combine() considered two HAL versions
replacement of each other when their package, interface and
instance are equal. (For example,
if 1.xml states audio@2.0::IDeviceFactory/default
and 2.xml states audio@4.0::IDeviceFactory/default
then generated matrix only requires one of them to exist.
With the introduction of <regex-instanece>, combine() only combines
two versions if the regex pattern *exactly matches*; that is (for
example)
if 1.xml states
camera@1.0::ICamera/legacy/0 AND camera@1.0::ICamera/legacy/[0-9]+
and 2.xml states
camera@3.0::ICamera/legacy/[0-9]+
combine() requires
camera@1.0::ICamera/legacy/0 AND
(camera@1.0::ICamera/legacy[0-9]+ OR camera@3.0::ICamera/legacy[0-9]+)
... because the pattern "legacy[0-9]+" are exactly the same. It will not
combine even if two regex patterns has the same meaning, e.g. when
one of them is "legacy/[0-9]{1,}".
Bug: 73738616
Test: libvintf_test
Test: vintf_object_test
Test: vts_treble_vintf_test
Change-Id: Ie34f0f1ccab1e942f6aa9e9e40aa20140f220844
Merged-In: Ie34f0f1ccab1e942f6aa9e9e40aa20140f220844
diff --git a/CompatibilityMatrix.cpp b/CompatibilityMatrix.cpp
index 840899d..88ecd26 100644
--- a/CompatibilityMatrix.cpp
+++ b/CompatibilityMatrix.cpp
@@ -82,19 +82,38 @@
// - Remove interface/instance from existingHal, and return a new MatrixHal (that is added
// to "this") that contains only interface/instance.
MatrixHal* CompatibilityMatrix::splitInstance(MatrixHal* existingHal, const std::string& interface,
- const std::string& instance) {
- if (!existingHal->hasInstance(interface, instance)) {
+ const std::string& instanceOrPattern, bool isRegex) {
+ bool found = false;
+ bool foundOthers = false;
+ existingHal->forEachInstance([&](const auto& matrixInstance) {
+ bool interfaceMatch = matrixInstance.interface() == interface;
+ bool instanceMatch = false;
+ if (matrixInstance.isRegex() && isRegex) {
+ instanceMatch = (matrixInstance.regexPattern() == instanceOrPattern);
+ } else if (!matrixInstance.isRegex() && !isRegex) {
+ instanceMatch = (matrixInstance.exactInstance() == instanceOrPattern);
+ }
+
+ bool match = interfaceMatch && instanceMatch;
+
+ found |= match;
+ foundOthers |= (!match);
+
+ return !found || !foundOthers;
+ });
+
+ if (!found) {
return nullptr;
}
- if (existingHal->hasOnlyInstance(interface, instance)) {
+ if (!foundOthers) {
return existingHal;
}
- existingHal->removeInstance(interface, instance);
+ existingHal->removeInstance(interface, instanceOrPattern, isRegex);
MatrixHal copy = *existingHal;
copy.clearInstances();
- copy.insertInstance(interface, instance);
+ copy.insertInstance(interface, instanceOrPattern, isRegex);
return addInternal(std::move(copy));
}
@@ -114,16 +133,22 @@
MatrixHal& halToAdd = pair.second;
std::set<std::pair<std::string, std::string>> insertedInstances;
+ std::set<std::pair<std::string, std::string>> insertedRegex;
auto existingHals = getHals(name);
halToAdd.forEachInstance([&](const std::vector<VersionRange>& versionRanges,
- const std::string& interface, const std::string& instance,
- bool /* isRegex */) {
+ const std::string& interface,
+ const std::string& instanceOrPattern, bool isRegex) {
for (auto* existingHal : existingHals) {
- MatrixHal* splitInstance = this->splitInstance(existingHal, interface, instance);
+ MatrixHal* splitInstance =
+ this->splitInstance(existingHal, interface, instanceOrPattern, isRegex);
if (splitInstance != nullptr) {
splitInstance->insertVersionRanges(versionRanges);
- insertedInstances.insert(std::make_pair(interface, instance));
+ if (isRegex) {
+ insertedRegex.insert(std::make_pair(interface, instanceOrPattern));
+ } else {
+ insertedInstances.insert(std::make_pair(interface, instanceOrPattern));
+ }
}
}
return true;
@@ -131,7 +156,10 @@
// Add the remaining instances.
for (const auto& pair : insertedInstances) {
- halToAdd.removeInstance(pair.first, pair.second);
+ halToAdd.removeInstance(pair.first, pair.second, false /* isRegex */);
+ }
+ for (const auto& pair : insertedRegex) {
+ halToAdd.removeInstance(pair.first, pair.second, true /* isRegex */);
}
if (halToAdd.instancesCount() > 0) {