Merge "Add product manifest and fragments."
diff --git a/VintfObject.cpp b/VintfObject.cpp
index e66bcbe..2badd18 100644
--- a/VintfObject.cpp
+++ b/VintfObject.cpp
@@ -339,12 +339,40 @@
return out->fetchAllInformation(getFileSystem().get(), kVendorLegacyMatrix, error);
}
+// Priority:
+// 1. /system/etc/vintf/manifest.xml
+// + /system/etc/vintf/manifest/*.xml if they exist
+// + /product/etc/vintf/manifest.xml if it exists
+// + /product/etc/vintf/manifest/*.xml if they exist
+// 2. (deprecated) /system/manifest.xml
status_t VintfObject::fetchFrameworkHalManifest(HalManifest* out, std::string* error) {
- HalManifest etcManifest;
- if (etcManifest.fetchAllInformation(getFileSystem().get(), kSystemManifest, error) == OK) {
- *out = std::move(etcManifest);
- return addDirectoryManifests(kSystemManifestFragmentDir, out, error);
+ auto systemEtcStatus = fetchOneHalManifest(kSystemManifest, out, error);
+ if (systemEtcStatus == OK) {
+ auto dirStatus = addDirectoryManifests(kSystemManifestFragmentDir, out, error);
+ if (dirStatus != OK) {
+ return dirStatus;
+ }
+
+ HalManifest productManifest;
+ auto productStatus = fetchOneHalManifest(kProductManifest, &productManifest, error);
+ if (productStatus != OK && productStatus != NAME_NOT_FOUND) {
+ return productStatus;
+ }
+ if (productStatus == OK) {
+ if (!out->addAll(&productManifest, error)) {
+ if (error) {
+ error->insert(0, "Cannot add " + kProductManifest + ":");
+ }
+ return UNKNOWN_ERROR;
+ }
+ }
+
+ return addDirectoryManifests(kProductManifestFragmentDir, out, error);
+ } else {
+ LOG(WARNING) << "Cannot fetch " << kSystemManifest << ": "
+ << (error ? *error : strerror(-systemEtcStatus));
}
+
return out->fetchAllInformation(getFileSystem().get(), kSystemLegacyManifest, error);
}
@@ -590,10 +618,12 @@
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 kProductManifest = kProductVintfDir + "manifest.xml";
const std::string kVendorManifestFragmentDir = kVendorVintfDir + "manifest/";
const std::string kSystemManifestFragmentDir = kSystemVintfDir + "manifest/";
const std::string kOdmManifestFragmentDir = kOdmVintfDir + "manifest/";
+const std::string kProductManifestFragmentDir = kProductVintfDir + "manifest/";
const std::string kVendorLegacyManifest = "/vendor/manifest.xml";
const std::string kVendorLegacyMatrix = "/vendor/compatibility_matrix.xml";
diff --git a/include/vintf/VintfObject.h b/include/vintf/VintfObject.h
index ceabf61..2b0616a 100644
--- a/include/vintf/VintfObject.h
+++ b/include/vintf/VintfObject.h
@@ -375,9 +375,11 @@
extern const std::string kVendorMatrix;
extern const std::string kOdmManifest;
extern const std::string kProductMatrix;
+extern const std::string kProductManifest;
extern const std::string kVendorManifestFragmentDir;
extern const std::string kSystemManifestFragmentDir;
extern const std::string kOdmManifestFragmentDir;
+extern const std::string kProductManifestFragmentDir;
extern const std::string kVendorLegacyManifest;
extern const std::string kVendorLegacyMatrix;
extern const std::string kSystemLegacyManifest;
diff --git a/test/vintf_object_tests.cpp b/test/vintf_object_tests.cpp
index f97d81f..0ae2946 100644
--- a/test/vintf_object_tests.cpp
+++ b/test/vintf_object_tests.cpp
@@ -368,6 +368,8 @@
.WillByDefault(Return(::android::OK));
ON_CALL(fetcher(), listFiles(StrEq(kOdmManifestFragmentDir), _, _))
.WillByDefault(Return(::android::OK));
+ ON_CALL(fetcher(), listFiles(StrEq(kProductManifestFragmentDir), _, _))
+ .WillByDefault(Return(::android::OK));
if (!productModel.empty()) {
ON_CALL(fetcher(),
@@ -415,6 +417,8 @@
.WillByDefault(Return(::android::OK));
// Don't fetch product matrix unless otherwise specified.
ON_CALL(fetcher(), fetch(StrEq(kProductMatrix), _)).WillByDefault(Return(NAME_NOT_FOUND));
+ // Don't fetch product manifest unless otherwise specified.
+ ON_CALL(fetcher(), fetch(StrEq(kProductManifest), _)).WillByDefault(Return(NAME_NOT_FOUND));
}
void setFakeProperties() {
@@ -452,6 +456,7 @@
void expectSystemManifest(size_t times = 1) {
EXPECT_CALL(fetcher(), fetch(StrEq(kSystemManifest), _)).Times(times);
+ EXPECT_CALL(fetcher(), fetch(StrEq(kProductManifest), _)).Times(times);
}
void expectVendorMatrix(size_t times = 1) {
@@ -1426,6 +1431,138 @@
EXPECT_TRUE(checkCompatibility({vendorManifestRequire2}, &error)) << error;
}
+const std::string systemEtcManifest =
+ "<manifest version=\"1.0\" type=\"framework\">\n"
+ " <hal format=\"hidl\">\n"
+ " <name>android.hardware.foo</name>\n"
+ " <transport>hwbinder</transport>\n"
+ " <fqname>@1.0::ISystemEtc/default</fqname>\n"
+ " </hal>\n"
+ "</manifest>\n";
+
+const std::string systemEtcManifestFrag =
+ "<manifest version=\"1.0\" type=\"framework\">\n"
+ " <hal format=\"hidl\">\n"
+ " <name>android.hardware.foo</name>\n"
+ " <transport>hwbinder</transport>\n"
+ " <fqname>@1.0::ISystemEtcFragment/default</fqname>\n"
+ " </hal>\n"
+ "</manifest>\n";
+
+const std::string productEtcManifest =
+ "<manifest version=\"1.0\" type=\"framework\">\n"
+ " <hal format=\"hidl\">\n"
+ " <name>android.hardware.foo</name>\n"
+ " <transport>hwbinder</transport>\n"
+ " <fqname>@1.0::IProductEtc/default</fqname>\n"
+ " </hal>\n"
+ "</manifest>\n";
+
+const std::string productEtcManifestFrag =
+ "<manifest version=\"1.0\" type=\"framework\">\n"
+ " <hal format=\"hidl\">\n"
+ " <name>android.hardware.foo</name>\n"
+ " <transport>hwbinder</transport>\n"
+ " <fqname>@1.0::IProductEtcFragment/default</fqname>\n"
+ " </hal>\n"
+ "</manifest>\n";
+
+using FrameworkManifestTestParam =
+ std::tuple<bool /* Existence of /system/etc/vintf/manifest.xml */,
+ bool /* Existence of /system/etc/vintf/manifest/fragment.xml */,
+ bool /* Existence of /product/etc/vintf/manifest.xml */,
+ bool /* Existence of /product/etc/vintf/manifest/fragment.xml */>;
+class FrameworkManifestTest : public VintfObjectTestBase,
+ public ::testing::WithParamInterface<FrameworkManifestTestParam> {
+ protected:
+ virtual void SetUp() {
+ VintfObjectTestBase::SetUp();
+ setFakeProperties();
+ }
+
+ // Set the existence of /system/etc/vintf/manifest.xml
+ void expectSystemManifest(bool exists) {
+ if (exists) {
+ expectFetchRepeatedly(kSystemManifest, systemEtcManifest);
+ } else {
+ expectFileNotExist(StrEq(kSystemManifest));
+ }
+ expectFileNotExist(StrEq(kSystemLegacyManifest));
+ }
+ // Set the existence of /system/etc/vintf/manifest/fragment.xml
+ void expectSystemManifestFragment(bool exists) {
+ if (exists) {
+ EXPECT_CALL(fetcher(), listFiles(StrEq(kSystemManifestFragmentDir), _, _))
+ .Times(AnyNumber())
+ .WillRepeatedly(Invoke([](const auto&, auto* out, auto*) {
+ *out = {"fragment.xml"};
+ return ::android::OK;
+ }));
+ expectFetchRepeatedly(kSystemManifestFragmentDir + "fragment.xml",
+ systemEtcManifestFrag);
+ } else {
+ EXPECT_CALL(fetcher(), listFiles(StrEq(kSystemManifestFragmentDir), _, _))
+ .Times(AnyNumber())
+ .WillRepeatedly(Return(::android::OK));
+ expectFileNotExist(kSystemManifestFragmentDir + "fragment.xml");
+ }
+ }
+ // Set the existence of /product/etc/vintf/manifest.xml
+ void expectProductManifest(bool exists) {
+ if (exists) {
+ expectFetchRepeatedly(kProductManifest, productEtcManifest);
+ } else {
+ expectFileNotExist(kProductManifest);
+ }
+ }
+ // Set the existence of /product/etc/vintf/manifest/fragment.xml
+ void expectProductManifestFragment(bool exists) {
+ if (exists) {
+ EXPECT_CALL(fetcher(), listFiles(StrEq(kProductManifestFragmentDir), _, _))
+ .Times(AnyNumber())
+ .WillRepeatedly(Invoke([](const auto&, auto* out, auto*) {
+ *out = {"fragment.xml"};
+ return ::android::OK;
+ }));
+ expectFetchRepeatedly(kProductManifestFragmentDir + "fragment.xml",
+ productEtcManifestFrag);
+ } else {
+ EXPECT_CALL(fetcher(), listFiles(StrEq(kProductManifestFragmentDir), _, _))
+ .Times(AnyNumber())
+ .WillRepeatedly(Return(::android::OK));
+ expectFileNotExist(kProductManifestFragmentDir + "fragment.xml");
+ }
+ }
+
+ void expectContainsInterface(const std::string& interface, bool contains = true) {
+ auto manifest = vintfObject->getFrameworkHalManifest();
+ ASSERT_NE(nullptr, manifest);
+ EXPECT_NE(manifest->getInstances("android.hardware.foo", {1, 0}, interface).empty(),
+ contains)
+ << interface << " is missing.";
+ }
+};
+
+TEST_P(FrameworkManifestTest, Existence) {
+ expectSystemManifest(std::get<0>(GetParam()));
+ expectSystemManifestFragment(std::get<1>(GetParam()));
+ expectProductManifest(std::get<2>(GetParam()));
+ expectProductManifestFragment(std::get<3>(GetParam()));
+
+ if (!std::get<0>(GetParam())) {
+ EXPECT_EQ(nullptr, vintfObject->getFrameworkHalManifest())
+ << "getFrameworkHalManifest must return nullptr if " << kSystemManifest
+ << " does not exist";
+ } else {
+ expectContainsInterface("ISystemEtc", std::get<0>(GetParam()));
+ expectContainsInterface("ISystemEtcFragment", std::get<1>(GetParam()));
+ expectContainsInterface("IProductEtc", std::get<2>(GetParam()));
+ expectContainsInterface("IProductEtcFragment", std::get<3>(GetParam()));
+ }
+}
+INSTANTIATE_TEST_SUITE_P(, FrameworkManifestTest,
+ ::testing::Combine(Bool(), Bool(), Bool(), Bool()));
+
} // namespace testing
} // namespace vintf
} // namespace android