Fetch framework matrix from /product/etc/vintf/compatibility_matrix.xml.
am: 73bde5914a
Change-Id: I2e9068c1fa5d28eec47f708205fc1cd71332e8f4
diff --git a/VintfObject.cpp b/VintfObject.cpp
index 64f4a61..1100977 100644
--- a/VintfObject.cpp
+++ b/VintfObject.cpp
@@ -144,8 +144,15 @@
status_t VintfObject::getCombinedFrameworkMatrix(
const std::shared_ptr<const HalManifest>& deviceManifest, CompatibilityMatrix* out,
std::string* error) {
- auto matrixFragments = getAllFrameworkMatrixLevels(error);
+ std::vector<Named<CompatibilityMatrix>> matrixFragments;
+ auto matrixFragmentsStatus = getAllFrameworkMatrixLevels(&matrixFragments, error);
+ if (matrixFragmentsStatus != OK) {
+ return matrixFragmentsStatus;
+ }
if (matrixFragments.empty()) {
+ if (error && error->empty()) {
+ *error = "Cannot get framework matrix for each FCM version for unknown error.";
+ }
return NAME_NOT_FOUND;
}
@@ -338,47 +345,66 @@
}
}
-std::vector<Named<CompatibilityMatrix>> VintfObject::getAllFrameworkMatrixLevels(
- std::string* error) {
- std::vector<std::string> fileNames;
- std::vector<Named<CompatibilityMatrix>> results;
+status_t VintfObject::getOneMatrix(const std::string& path, Named<CompatibilityMatrix>* out,
+ std::string* error) {
+ std::string content;
+ status_t status = getFileSystem()->fetch(path, &content, error);
+ if (status != OK) {
+ return status;
+ }
+ if (!gCompatibilityMatrixConverter(&out->object, content, error)) {
+ if (error) {
+ error->insert(0, "Cannot parse " + path + ": ");
+ }
+ return BAD_VALUE;
+ }
+ out->name = path;
+ return OK;
+}
- if (getFileSystem()->listFiles(kSystemVintfDir, &fileNames, error) != OK) {
- return {};
+status_t VintfObject::getAllFrameworkMatrixLevels(std::vector<Named<CompatibilityMatrix>>* results,
+ std::string* error) {
+ std::vector<std::string> fileNames;
+
+ status_t listStatus = getFileSystem()->listFiles(kSystemVintfDir, &fileNames, error);
+ if (listStatus != OK) {
+ return listStatus;
}
for (const std::string& fileName : fileNames) {
std::string path = kSystemVintfDir + fileName;
-
- std::string content;
- std::string fetchError;
- status_t status = getFileSystem()->fetch(path, &content, &fetchError);
- if (status != OK) {
- appendLine(error, "Framework Matrix: Ignore file " + path + ": " + fetchError);
+ Named<CompatibilityMatrix> namedMatrix;
+ std::string matrixError;
+ status_t matrixStatus = getOneMatrix(path, &namedMatrix, &matrixError);
+ if (matrixStatus != OK) {
+ // System manifests and matrices share the same dir. Client may not have enough
+ // permissions to read system manifests, or may not be able to parse it.
+ auto logLevel = matrixStatus == BAD_VALUE ? base::DEBUG : base::ERROR;
+ LOG(logLevel) << "Framework Matrix: Ignore file " << path << ": " << matrixError;
continue;
}
-
- auto it = results.emplace(results.end());
- std::string parseError;
- if (!gCompatibilityMatrixConverter(&it->object, content, &parseError)) {
- appendLine(error, "Framework Matrix: Ignore file " + path + ": " + parseError);
- results.erase(it);
- continue;
- }
+ results->emplace_back(std::move(namedMatrix));
}
- if (results.empty()) {
- if (error) {
- error->insert(0, "No framework matrices under " + kSystemVintfDir +
- " can be fetched or parsed.\n");
- }
+ Named<CompatibilityMatrix> productMatrix;
+ std::string productError;
+ status_t productStatus = getOneMatrix(kProductMatrix, &productMatrix, &productError);
+ if (productStatus == OK) {
+ results->emplace_back(std::move(productMatrix));
+ } else if (productStatus == NAME_NOT_FOUND) {
+ LOG(DEBUG) << "Framework Matrix: missing " << kProductMatrix;
} else {
- if (error && !error->empty()) {
- LOG(WARNING) << *error;
- *error = "";
- }
+ if (error) *error = std::move(productError);
+ return productStatus;
}
- return results;
+ if (results->empty()) {
+ if (error) {
+ *error =
+ "No framework matrices under " + kSystemVintfDir + " can be fetched or parsed.\n";
+ }
+ return NAME_NOT_FOUND;
+ }
+ return OK;
}
std::shared_ptr<const RuntimeInfo> VintfObject::GetRuntimeInfo(bool skipCache,
@@ -541,11 +567,13 @@
const std::string kSystemVintfDir = "/system/etc/vintf/";
const std::string kVendorVintfDir = "/vendor/etc/vintf/";
const std::string kOdmVintfDir = "/odm/etc/vintf/";
+const std::string kProductVintfDir = "/product/etc/vintf/";
const std::string kVendorManifest = kVendorVintfDir + "manifest.xml";
const std::string kSystemManifest = kSystemVintfDir + "manifest.xml";
const std::string kVendorMatrix = kVendorVintfDir + "compatibility_matrix.xml";
const std::string kOdmManifest = kOdmVintfDir + "manifest.xml";
+const std::string kProductMatrix = kProductVintfDir + "compatibility_matrix.xml";
const std::string kVendorManifestFragmentDir = kVendorVintfDir + "manifest/";
const std::string kSystemManifestFragmentDir = kSystemVintfDir + "manifest/";
@@ -560,9 +588,17 @@
std::vector<std::string> dumpFileList() {
return {
- kSystemVintfDir, kVendorVintfDir, kOdmVintfDir, kOdmLegacyVintfDir,
-
- kVendorLegacyManifest, kVendorLegacyMatrix, kSystemLegacyManifest, kSystemLegacyMatrix,
+ // clang-format off
+ kSystemVintfDir,
+ kVendorVintfDir,
+ kOdmVintfDir,
+ kProductVintfDir,
+ kOdmLegacyVintfDir,
+ kVendorLegacyManifest,
+ kVendorLegacyMatrix,
+ kSystemLegacyManifest,
+ kSystemLegacyMatrix,
+ // clang-format on
};
}
@@ -658,10 +694,15 @@
return GetInstance()->checkDeprecation(listInstances, error);
}
int32_t VintfObject::checkDeprecation(const ListInstances& listInstances, std::string* error) {
- auto matrixFragments = getAllFrameworkMatrixLevels(error);
+ std::vector<Named<CompatibilityMatrix>> matrixFragments;
+ auto matrixFragmentsStatus = getAllFrameworkMatrixLevels(&matrixFragments, error);
+ if (matrixFragmentsStatus != OK) {
+ return matrixFragmentsStatus;
+ }
if (matrixFragments.empty()) {
- if (error && error->empty())
+ if (error && error->empty()) {
*error = "Cannot get framework matrix for each FCM version for unknown error.";
+ }
return NAME_NOT_FOUND;
}
auto deviceManifest = getDeviceHalManifest();
diff --git a/include/vintf/VintfObject.h b/include/vintf/VintfObject.h
index 4162843..e1a4501 100644
--- a/include/vintf/VintfObject.h
+++ b/include/vintf/VintfObject.h
@@ -305,8 +305,10 @@
status_t getCombinedFrameworkMatrix(const std::shared_ptr<const HalManifest>& deviceManifest,
CompatibilityMatrix* out, std::string* error = nullptr);
- std::vector<Named<CompatibilityMatrix>> getAllFrameworkMatrixLevels(
- std::string* error = nullptr);
+ status_t getAllFrameworkMatrixLevels(std::vector<Named<CompatibilityMatrix>>* out,
+ std::string* error = nullptr);
+ status_t getOneMatrix(const std::string& path, Named<CompatibilityMatrix>* out,
+ std::string* error = nullptr);
status_t addDirectoryManifests(const std::string& directory, HalManifest* manifests,
std::string* error = nullptr);
status_t fetchDeviceHalManifest(HalManifest* out, std::string* error = nullptr);
@@ -365,12 +367,14 @@
extern const std::string kSystemVintfDir;
extern const std::string kVendorVintfDir;
extern const std::string kOdmVintfDir;
+extern const std::string kProductVintfDir;
extern const std::string kOdmLegacyVintfDir;
extern const std::string kOdmLegacyManifest;
extern const std::string kVendorManifest;
extern const std::string kSystemManifest;
extern const std::string kVendorMatrix;
extern const std::string kOdmManifest;
+extern const std::string kProductMatrix;
extern const std::string kVendorManifestFragmentDir;
extern const std::string kSystemManifestFragmentDir;
extern const std::string kOdmManifestFragmentDir;
diff --git a/test/vintf_object_tests.cpp b/test/vintf_object_tests.cpp
index 6d1c1dd..92e2ce9 100644
--- a/test/vintf_object_tests.cpp
+++ b/test/vintf_object_tests.cpp
@@ -392,6 +392,8 @@
// Don't list /system/etc/vintf unless otherwise specified.
ON_CALL(fetcher(), listFiles(StrEq(kSystemVintfDir), _, _))
.WillByDefault(Return(::android::OK));
+ // Don't fetch product matrix unless otherwise specified.
+ ON_CALL(fetcher(), fetch(StrEq(kProductMatrix), _)).WillByDefault(Return(NAME_NOT_FOUND));
}
void setFakeProperties() {
@@ -437,6 +439,7 @@
}
void expectSystemMatrix(size_t times = 1) {
+ EXPECT_CALL(fetcher(), fetch(StrEq(kProductMatrix), _)).Times(times);
EXPECT_CALL(fetcher(), fetch(StrEq(kSystemLegacyMatrix), _)).Times(times);
}
@@ -694,12 +697,55 @@
"<compatibility-matrix version=\"1.0\" type=\"framework\" level=\"1\"/>");
expectFetch(kSystemVintfDir + "compatibility_matrix.empty.xml",
"<compatibility-matrix version=\"1.0\" type=\"framework\"/>");
+ expectFileNotExist(StrEq(kProductMatrix));
expectFetch(kVendorManifest, "<manifest version=\"1.0\" type=\"device\" />\n");
- expectSystemMatrix(0);
+ expectNeverFetch(kSystemLegacyMatrix);
EXPECT_NE(nullptr, vintfObject->getFrameworkCompatibilityMatrix(true /* skipCache */));
}
+// Test product compatibility matrix is fetched
+TEST_F(VintfObjectTest, ProductCompatibilityMatrix) {
+ EXPECT_CALL(fetcher(), listFiles(StrEq(kSystemVintfDir), _, _))
+ .WillOnce(Invoke([](const auto&, auto* out, auto*) {
+ *out = {
+ "compatibility_matrix.1.xml",
+ "compatibility_matrix.empty.xml",
+ };
+ return ::android::OK;
+ }));
+ expectFetch(kSystemVintfDir + "compatibility_matrix.1.xml",
+ "<compatibility-matrix version=\"1.0\" type=\"framework\" level=\"1\"/>");
+ expectFetch(kSystemVintfDir + "compatibility_matrix.empty.xml",
+ "<compatibility-matrix version=\"1.0\" type=\"framework\"/>");
+ expectFetch(kProductMatrix,
+ "<compatibility-matrix version=\"1.0\" type=\"framework\">\n"
+ " <hal format=\"hidl\" optional=\"true\">\n"
+ " <name>android.hardware.foo</name>\n"
+ " <version>1.0</version>\n"
+ " <interface>\n"
+ " <name>IFoo</name>\n"
+ " <instance>default</instance>\n"
+ " </interface>\n"
+ " </hal>\n"
+ "</compatibility-matrix>\n");
+ expectFetch(kVendorManifest, "<manifest version=\"1.0\" type=\"device\" />\n");
+ expectNeverFetch(kSystemLegacyMatrix);
+
+ auto fcm = vintfObject->getFrameworkCompatibilityMatrix(true /* skipCache */);
+ ASSERT_NE(nullptr, fcm);
+
+ FqInstance expectInstance;
+ EXPECT_TRUE(expectInstance.setTo("android.hardware.foo@1.0::IFoo/default"));
+ bool found = false;
+ fcm->forEachInstance([&found, &expectInstance](const auto& matrixInstance) {
+ found |= matrixInstance.isSatisfiedBy(expectInstance);
+ return !found; // continue if not found
+ });
+ EXPECT_TRUE(found) << "android.hardware.foo@1.0::IFoo/default should be found in matrix:\n"
+ << gCompatibilityMatrixConverter(*fcm);
+}
+
const std::string vendorEtcManifest =
"<manifest version=\"1.0\" type=\"device\">\n"
" <hal format=\"hidl\">\n"
@@ -938,7 +984,8 @@
.WillOnce(Return(::android::OK));
expectFetch(kSystemVintfDir + "compatibility_matrix.1.xml", systemMatrixLevel1);
expectFetch(kSystemVintfDir + "compatibility_matrix.2.xml", systemMatrixLevel2);
- expectSystemMatrix(0);
+ expectFileNotExist(StrEq(kProductMatrix));
+ expectNeverFetch(kSystemLegacyMatrix);
expectFetch(kVendorManifest,
"<manifest version=\"1.0\" type=\"device\" target-level=\"2\"/>");
@@ -1048,7 +1095,8 @@
expectFetchRepeatedly(kSystemVintfDir + getFileName(i), content);
++i;
}
- expectSystemMatrix(0);
+ expectFileNotExist(kProductMatrix);
+ expectNeverFetch(kSystemLegacyMatrix);
expectFileNotExist(StartsWith("/odm/"));
}
void expectTargetFcmVersion(size_t level) {