Add <xmlfile> to manifest / comp mat.
manifest.xml is allowed to contain <xmlfile> that is similar to:
<xmlfile>
<name>media_profile</name>
<version>1.0</version>
<path>/path/to/media_profile_v1_0.xml</path>
</xmlfile>
For compatibility-matrix.xml
<xmlfile format="dtd" optional="false">
<name>media_profile</name>
<version>1.0-1</version>
<path>/path/to/media_profile_v1_1.dtd</path>
</xmlfile>
The <path> tag is optional. See test/main.cpp for examples.
Test: libvintf_test
Test: vintf_object_test
Bug: 38359330
Change-Id: I0a921f32d023e1ba9c54ea6e898bb385fc7abd4f
diff --git a/Android.bp b/Android.bp
index 22224e9..5a67c5f 100644
--- a/Android.bp
+++ b/Android.bp
@@ -47,6 +47,7 @@
"MatrixKernel.cpp",
"TransportArch.cpp",
"VintfObject.cpp",
+ "XmlFile.cpp",
"utils.cpp",
],
@@ -117,6 +118,7 @@
"MatrixKernel.cpp",
"TransportArch.cpp",
"VintfObject.cpp",
+ "XmlFile.cpp",
"test/RuntimeInfo-fake.cpp",
"test/utils-fake.cpp",
],
diff --git a/CompatibilityMatrix.cpp b/CompatibilityMatrix.cpp
index 627c238..907ac8c 100644
--- a/CompatibilityMatrix.cpp
+++ b/CompatibilityMatrix.cpp
@@ -58,14 +58,12 @@
}
bool operator==(const CompatibilityMatrix &lft, const CompatibilityMatrix &rgt) {
- return lft.mType == rgt.mType &&
- lft.mHals == rgt.mHals &&
- (lft.mType != SchemaType::DEVICE || (
- lft.device.mVndk == rgt.device.mVndk)) &&
- (lft.mType != SchemaType::FRAMEWORK || (
- lft.framework.mKernels == rgt.framework.mKernels &&
- lft.framework.mSepolicy == rgt.framework.mSepolicy &&
- lft.framework.mAvbMetaVersion == rgt.framework.mAvbMetaVersion));
+ return lft.mType == rgt.mType && lft.mHals == rgt.mHals && lft.mXmlFiles == rgt.mXmlFiles &&
+ (lft.mType != SchemaType::DEVICE || (lft.device.mVndk == rgt.device.mVndk)) &&
+ (lft.mType != SchemaType::FRAMEWORK ||
+ (lft.framework.mKernels == rgt.framework.mKernels &&
+ lft.framework.mSepolicy == rgt.framework.mSepolicy &&
+ lft.framework.mAvbMetaVersion == rgt.framework.mAvbMetaVersion));
}
} // namespace vintf
diff --git a/HalManifest.cpp b/HalManifest.cpp
index efa543e..5ebe083 100644
--- a/HalManifest.cpp
+++ b/HalManifest.cpp
@@ -55,6 +55,16 @@
return true;
}
+bool HalManifest::shouldAddXmlFile(const ManifestXmlFile& xmlFile) const {
+ auto existingXmlFiles = getXmlFiles(xmlFile.name());
+ for (auto it = existingXmlFiles.first; it != existingXmlFiles.second; ++it) {
+ if (xmlFile.version() == it->second.version()) {
+ return false;
+ }
+ }
+ return true;
+}
+
std::set<std::string> HalManifest::getHalNames() const {
std::set<std::string> names{};
for (const auto &hal : mHals) {
@@ -365,12 +375,10 @@
}
bool operator==(const HalManifest &lft, const HalManifest &rgt) {
- return lft.mType == rgt.mType &&
- lft.mHals == rgt.mHals &&
- (lft.mType != SchemaType::DEVICE || (
- lft.device.mSepolicyVersion == rgt.device.mSepolicyVersion)) &&
- (lft.mType != SchemaType::FRAMEWORK || (
- lft.framework.mVndks == rgt.framework.mVndks));
+ return lft.mType == rgt.mType && lft.mHals == rgt.mHals && lft.mXmlFiles == rgt.mXmlFiles &&
+ (lft.mType != SchemaType::DEVICE ||
+ (lft.device.mSepolicyVersion == rgt.device.mSepolicyVersion)) &&
+ (lft.mType != SchemaType::FRAMEWORK || (lft.framework.mVndks == rgt.framework.mVndks));
}
} // namespace vintf
diff --git a/XmlFile.cpp b/XmlFile.cpp
new file mode 100644
index 0000000..695b3d4
--- /dev/null
+++ b/XmlFile.cpp
@@ -0,0 +1,34 @@
+/*
+ * Copyright (C) 2017 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#include "XmlFile.h"
+
+namespace android {
+namespace vintf {
+
+bool MatrixXmlFile::operator==(const MatrixXmlFile& other) const {
+ return name() == other.name() && overriddenPath() == other.overriddenPath() &&
+ optional() == other.optional() && format() == other.format() &&
+ versionRange() == other.versionRange();
+}
+
+bool ManifestXmlFile::operator==(const ManifestXmlFile& other) const {
+ return name() == other.name() && overriddenPath() == other.overriddenPath() &&
+ version() == other.version();
+}
+
+} // namespace vintf
+} // namespace android
diff --git a/include/vintf/CompatibilityMatrix.h b/include/vintf/CompatibilityMatrix.h
index 228fe5e..66e5f8d 100644
--- a/include/vintf/CompatibilityMatrix.h
+++ b/include/vintf/CompatibilityMatrix.h
@@ -29,12 +29,13 @@
#include "SchemaType.h"
#include "Sepolicy.h"
#include "Vndk.h"
+#include "XmlFileGroup.h"
namespace android {
namespace vintf {
// Compatibility matrix defines what hardware does the framework requires.
-struct CompatibilityMatrix : public HalGroup<MatrixHal> {
+struct CompatibilityMatrix : public HalGroup<MatrixHal>, public XmlFileGroup<MatrixXmlFile> {
// Create a framework compatibility matrix.
CompatibilityMatrix() : mType(SchemaType::FRAMEWORK) {};
diff --git a/include/vintf/HalManifest.h b/include/vintf/HalManifest.h
index 9e01330..2f78301 100644
--- a/include/vintf/HalManifest.h
+++ b/include/vintf/HalManifest.h
@@ -29,6 +29,7 @@
#include "SchemaType.h"
#include "Version.h"
#include "Vndk.h"
+#include "XmlFileGroup.h"
namespace android {
namespace vintf {
@@ -38,7 +39,7 @@
// A HalManifest is reported by the hardware and query-able from
// framework code. This is the API for the framework.
-struct HalManifest : public HalGroup<ManifestHal> {
+struct HalManifest : public HalGroup<ManifestHal>, public XmlFileGroup<ManifestXmlFile> {
public:
// manifest.version
constexpr static Version kVersion{1, 0};
@@ -123,6 +124,7 @@
protected:
// Check before add()
bool shouldAdd(const ManifestHal& toAdd) const override;
+ bool shouldAddXmlFile(const ManifestXmlFile& toAdd) const override;
private:
friend struct HalManifestConverter;
@@ -141,6 +143,9 @@
// Check if all instances in matrixHal is supported in this manifest.
bool isCompatible(const MatrixHal& matrixHal) const;
+ std::vector<std::string> checkIncompatibleXmlFiles(const CompatibilityMatrix& mat,
+ bool includeOptional = true) const;
+
SchemaType mType;
// entries for device hal manifest only
diff --git a/include/vintf/MapValueIterator.h b/include/vintf/MapValueIterator.h
index 3a41e82..ec9fb19 100644
--- a/include/vintf/MapValueIterator.h
+++ b/include/vintf/MapValueIterator.h
@@ -92,7 +92,9 @@
return IteratorImpl<is_const>(mMap.end());
}
- private:
+ bool empty() const { return begin() == end(); }
+
+ private:
map_ref mMap;
};
diff --git a/include/vintf/Version.h b/include/vintf/Version.h
index c712269..0f38391 100644
--- a/include/vintf/Version.h
+++ b/include/vintf/Version.h
@@ -55,6 +55,13 @@
inline bool operator>=(const Version &other) const {
return !((*this) < other);
}
+ // Version(2, 1).minorAtLeast(Version(1, 0)) == false
+ // Version(2, 1).minorAtLeast(Version(2, 0)) == true
+ // Version(2, 1).minorAtLeast(Version(2, 1)) == true
+ // Version(2, 1).minorAtLeast(Version(2, 2)) == false
+ inline bool minorAtLeast(const Version& other) const {
+ return majorVer == other.majorVer && minorVer >= other.minorVer;
+ }
};
struct KernelVersion {
diff --git a/include/vintf/XmlFile.h b/include/vintf/XmlFile.h
new file mode 100644
index 0000000..787e217
--- /dev/null
+++ b/include/vintf/XmlFile.h
@@ -0,0 +1,67 @@
+/*
+ * Copyright (C) 2017 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#ifndef ANDROID_VINTF_XML_FILE_H
+#define ANDROID_VINTF_XML_FILE_H
+
+#include <string>
+
+#include "Version.h"
+#include "VersionRange.h"
+#include "XmlSchemaFormat.h"
+
+namespace android {
+namespace vintf {
+
+struct XmlFile {
+ public:
+ inline const std::string& name() const { return mName; }
+ inline const std::string& overriddenPath() const { return mOverriddenPath; }
+
+ protected:
+ std::string mName;
+ std::string mOverriddenPath;
+};
+
+// An <xmlfile> entry in matrix
+struct MatrixXmlFile : public XmlFile {
+ inline bool optional() const { return mOptional; }
+ inline XmlSchemaFormat format() const { return mFormat; }
+ inline const VersionRange& versionRange() const { return mVersionRange; }
+ bool operator==(const MatrixXmlFile& other) const;
+
+ private:
+ friend struct MatrixXmlFileConverter;
+ friend struct LibVintfTest;
+ bool mOptional;
+ XmlSchemaFormat mFormat;
+ VersionRange mVersionRange;
+};
+
+// An <xmlfile> entry in manifest
+struct ManifestXmlFile : public XmlFile {
+ inline const Version& version() const { return mVersion; }
+ bool operator==(const ManifestXmlFile& other) const;
+
+ private:
+ friend struct ManifestXmlFileConverter;
+ friend struct LibVintfTest;
+ Version mVersion;
+};
+
+} // namespace vintf
+} // namespace android
+#endif // ANDROID_VINTF_XML_FILE_H
diff --git a/include/vintf/XmlFileGroup.h b/include/vintf/XmlFileGroup.h
new file mode 100644
index 0000000..be2bb73
--- /dev/null
+++ b/include/vintf/XmlFileGroup.h
@@ -0,0 +1,68 @@
+/*
+ * Copyright (C) 2017 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#ifndef ANDROID_VINTF_XML_FILE_GROUP_H
+#define ANDROID_VINTF_XML_FILE_GROUP_H
+
+#include <map>
+#include <type_traits>
+
+#include "MapValueIterator.h"
+#include "XmlFile.h"
+
+namespace android {
+namespace vintf {
+
+// A XmlFileGroup is a wrapped multimap from name to T, where T
+// must be a subclass of XmlFile.
+template <typename T>
+struct XmlFileGroup {
+ static_assert(std::is_base_of<XmlFile, T>::value, "T must be a subclass of XmlFile");
+
+ private:
+ using map = std::multimap<std::string, T>;
+ using const_range = std::pair<typename map::const_iterator, typename map::const_iterator>;
+
+ public:
+ virtual ~XmlFileGroup() {}
+
+ bool addXmlFile(T&& t) {
+ if (!shouldAddXmlFile(t)) {
+ return false;
+ }
+ std::string name = t.name();
+ mXmlFiles.emplace(std::move(name), std::move(t));
+ return true;
+ }
+
+ virtual bool shouldAddXmlFile(const T&) const { return true; }
+
+ const_range getXmlFiles(const std::string& key) const { return mXmlFiles.equal_range(key); }
+
+ // Return an iterable to all T objects. Call it as follows:
+ // for (const auto& e : vm.getXmlFiles()) { }
+ ConstMultiMapValueIterable<std::string, T> getXmlFiles() const {
+ return ConstMultiMapValueIterable<std::string, T>(mXmlFiles);
+ }
+
+ protected:
+ map mXmlFiles;
+};
+
+} // namespace vintf
+} // namespace android
+
+#endif // ANDROID_VINTF_XML_FILE_GROUP_H
diff --git a/include/vintf/XmlSchemaFormat.h b/include/vintf/XmlSchemaFormat.h
new file mode 100644
index 0000000..32a42b6
--- /dev/null
+++ b/include/vintf/XmlSchemaFormat.h
@@ -0,0 +1,37 @@
+/*
+ * Copyright (C) 2017 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#ifndef ANDROID_VINTF_XML_SCHEMA_FORMAT_H
+#define ANDROID_VINTF_XML_SCHEMA_FORMAT_H
+
+#include <array>
+#include <string>
+
+namespace android {
+namespace vintf {
+
+enum XmlSchemaFormat {
+ DTD,
+ XSD,
+};
+
+static const std::array<std::string, 2> gXmlSchemaFormatStrings = {{
+ "dtd", "xsd",
+}};
+
+} // namespace vintf
+} // namespace android
+#endif // ANDROID_VINTF_XML_SCHEMA_FORMAT_H
diff --git a/include/vintf/parse_string.h b/include/vintf/parse_string.h
index 83a4904..2cfd41e 100644
--- a/include/vintf/parse_string.h
+++ b/include/vintf/parse_string.h
@@ -34,6 +34,7 @@
std::ostream &operator<<(std::ostream &os, KernelConfigType il);
std::ostream &operator<<(std::ostream &os, Tristate tr);
std::ostream &operator<<(std::ostream &os, SchemaType ksv);
+std::ostream& operator<<(std::ostream& os, XmlSchemaFormat f);
std::ostream &operator<<(std::ostream &os, const ManifestHal &hal);
std::ostream &operator<<(std::ostream &os, const Version &ver);
std::ostream &operator<<(std::ostream &os, const VersionRange &vr);
@@ -58,6 +59,7 @@
bool parse(const std::string &s, KernelConfigKey *key);
bool parse(const std::string &s, Tristate *tr);
bool parse(const std::string &s, SchemaType *ver);
+bool parse(const std::string& s, XmlSchemaFormat* ver);
bool parse(const std::string &s, KernelSepolicyVersion *ksv);
bool parse(const std::string &s, Version *ver);
bool parse(const std::string &s, VersionRange *vr);
diff --git a/parse_string.cpp b/parse_string.cpp
index d412ac4..4d7ae9a 100644
--- a/parse_string.cpp
+++ b/parse_string.cpp
@@ -97,6 +97,7 @@
DEFINE_PARSE_STREAMIN_FOR_ENUM(KernelConfigType);
DEFINE_PARSE_STREAMIN_FOR_ENUM(Tristate);
DEFINE_PARSE_STREAMIN_FOR_ENUM(SchemaType);
+DEFINE_PARSE_STREAMIN_FOR_ENUM(XmlSchemaFormat);
std::ostream &operator<<(std::ostream &os, const KernelConfigTypedValue &kctv) {
switch (kctv.mType) {
diff --git a/parse_xml.cpp b/parse_xml.cpp
index 557da76..f12df00 100644
--- a/parse_xml.cpp
+++ b/parse_xml.cpp
@@ -265,6 +265,13 @@
return true;
}
+ inline bool parseOptionalTextElement(NodeType* root, const std::string& elementName,
+ std::string&& defaultValue, std::string* s) const {
+ NodeType* child = getChild(root, elementName);
+ *s = child == nullptr ? std::move(defaultValue) : getText(child);
+ return true;
+ }
+
inline bool parseTextElements(NodeType *root, const std::string &elementName,
std::vector<std::string> *v) const {
auto nodes = getChildren(root, elementName);
@@ -610,17 +617,40 @@
};
const HalManifestSepolicyConverter halManifestSepolicyConverter{};
+struct ManifestXmlFileConverter : public XmlNodeConverter<ManifestXmlFile> {
+ std::string elementName() const override { return "xmlfile"; }
+ void mutateNode(const ManifestXmlFile& f, NodeType* root, DocType* d) const override {
+ appendTextElement(root, "name", f.name(), d);
+ appendChild(root, versionConverter(f.version(), d));
+ if (!f.overriddenPath().empty()) {
+ appendTextElement(root, "path", f.overriddenPath(), d);
+ }
+ }
+ bool buildObject(ManifestXmlFile* object, NodeType* root) const override {
+ if (!parseTextElement(root, "name", &object->mName) ||
+ !parseChild(root, versionConverter, &object->mVersion) ||
+ !parseOptionalTextElement(root, "path", {}, &object->mOverriddenPath)) {
+ return false;
+ }
+ return true;
+ }
+};
+const ManifestXmlFileConverter manifestXmlFileConverter{};
+
struct HalManifestConverter : public XmlNodeConverter<HalManifest> {
std::string elementName() const override { return "manifest"; }
void mutateNode(const HalManifest &m, NodeType *root, DocType *d) const override {
appendAttr(root, "version", HalManifest::kVersion);
appendAttr(root, "type", m.mType);
+
appendChildren(root, manifestHalConverter, m.getHals(), d);
if (m.mType == SchemaType::DEVICE) {
appendChild(root, halManifestSepolicyConverter(m.device.mSepolicyVersion, d));
} else if (m.mType == SchemaType::FRAMEWORK) {
appendChildren(root, vndkConverter, m.framework.mVndks, d);
}
+
+ appendChildren(root, manifestXmlFileConverter, m.getXmlFiles(), d);
}
bool buildObject(HalManifest *object, NodeType *root) const override {
Version version;
@@ -661,6 +691,20 @@
return false;
}
}
+
+ std::vector<ManifestXmlFile> xmlFiles;
+ if (!parseChildren(root, manifestXmlFileConverter, &xmlFiles)) {
+ return false;
+ }
+ for (auto&& xmlFile : xmlFiles) {
+ std::string description{xmlFile.name()};
+ if (!object->addXmlFile(std::move(xmlFile))) {
+ this->mLastError = "Duplicated manifest.xmlfile entry " + description +
+ "; entries cannot have duplicated name and version";
+ return false;
+ }
+ }
+
return true;
}
};
@@ -679,6 +723,30 @@
};
const AvbConverter avbConverter{};
+struct MatrixXmlFileConverter : public XmlNodeConverter<MatrixXmlFile> {
+ std::string elementName() const override { return "xmlfile"; }
+ void mutateNode(const MatrixXmlFile& f, NodeType* root, DocType* d) const override {
+ appendTextElement(root, "name", f.name(), d);
+ appendAttr(root, "format", f.format());
+ appendAttr(root, "optional", f.optional());
+ appendChild(root, versionRangeConverter(f.versionRange(), d));
+ if (!f.overriddenPath().empty()) {
+ appendTextElement(root, "path", f.overriddenPath(), d);
+ }
+ }
+ bool buildObject(MatrixXmlFile* object, NodeType* root) const override {
+ if (!parseTextElement(root, "name", &object->mName) ||
+ !parseAttr(root, "format", &object->mFormat) ||
+ !parseOptionalAttr(root, "optional", false, &object->mOptional) ||
+ !parseChild(root, versionRangeConverter, &object->mVersionRange) ||
+ !parseOptionalTextElement(root, "path", {}, &object->mOverriddenPath)) {
+ return false;
+ }
+ return true;
+ }
+};
+const MatrixXmlFileConverter matrixXmlFileConverter{};
+
struct CompatibilityMatrixConverter : public XmlNodeConverter<CompatibilityMatrix> {
std::string elementName() const override { return "compatibility-matrix"; }
void mutateNode(const CompatibilityMatrix &m, NodeType *root, DocType *d) const override {
@@ -692,6 +760,8 @@
} else if (m.mType == SchemaType::DEVICE) {
appendChild(root, vndkConverter(m.device.mVndk, d));
}
+
+ appendChildren(root, matrixXmlFileConverter, m.getXmlFiles(), d);
}
bool buildObject(CompatibilityMatrix *object, NodeType *root) const override {
Version version;
@@ -728,6 +798,24 @@
return false;
}
}
+
+ std::vector<MatrixXmlFile> xmlFiles;
+ if (!parseChildren(root, matrixXmlFileConverter, &xmlFiles)) {
+ return false;
+ }
+ for (auto&& xmlFile : xmlFiles) {
+ if (!xmlFile.optional()) {
+ this->mLastError = "compatibility-matrix.xmlfile entry " + xmlFile.name() +
+ " has to be optional for compatibility matrix version 1.0";
+ return false;
+ }
+ std::string description{xmlFile.name()};
+ if (!object->addXmlFile(std::move(xmlFile))) {
+ this->mLastError = "Duplicated compatibility-matrix.xmlfile entry " + description;
+ return false;
+ }
+ }
+
return true;
}
};
diff --git a/test/main.cpp b/test/main.cpp
index 6ce1e23..090fd3d 100644
--- a/test/main.cpp
+++ b/test/main.cpp
@@ -52,6 +52,14 @@
bool add(HalManifest &vm, ManifestHal &&hal) {
return vm.add(std::move(hal));
}
+ void addXmlFile(CompatibilityMatrix& cm, std::string name, VersionRange range) {
+ MatrixXmlFile f;
+ f.mName = name;
+ f.mVersionRange = range;
+ f.mFormat = XmlSchemaFormat::DTD;
+ f.mOptional = true;
+ cm.addXmlFile(std::move(f));
+ }
void set(CompatibilityMatrix &cm, Sepolicy &&sepolicy) {
cm.framework.mSepolicy = sepolicy;
}
@@ -120,6 +128,14 @@
return vm;
}
+ HalManifest testDeviceManifestWithXmlFile() {
+ HalManifest vm = testDeviceManifest();
+ ManifestXmlFile xmlFile;
+ xmlFile.mName = "media_profile";
+ xmlFile.mVersion = {1, 0};
+ vm.addXmlFile(std::move(xmlFile));
+ return vm;
+ }
HalManifest testFrameworkManfiest() {
HalManifest vm;
vm.mType = SchemaType::FRAMEWORK;
@@ -1101,6 +1117,87 @@
EXPECT_TRUE(manifest.checkCompatibility(matrix, &error)) << error;
}
+/////////////////// xmlfile tests
+
+TEST_F(LibVintfTest, HalManifestConverterXmlFile) {
+ HalManifest vm = testDeviceManifestWithXmlFile();
+ std::string xml = gHalManifestConverter(vm);
+ EXPECT_EQ(xml,
+ "<manifest version=\"1.0\" type=\"device\">\n"
+ " <hal format=\"hidl\">\n"
+ " <name>android.hardware.camera</name>\n"
+ " <transport>hwbinder</transport>\n"
+ " <version>2.0</version>\n"
+ " <interface>\n"
+ " <name>IBetterCamera</name>\n"
+ " <instance>camera</instance>\n"
+ " </interface>\n"
+ " <interface>\n"
+ " <name>ICamera</name>\n"
+ " <instance>default</instance>\n"
+ " <instance>legacy/0</instance>\n"
+ " </interface>\n"
+ " </hal>\n"
+ " <hal format=\"hidl\">\n"
+ " <name>android.hardware.nfc</name>\n"
+ " <transport arch=\"32+64\">passthrough</transport>\n"
+ " <version>1.0</version>\n"
+ " <interface>\n"
+ " <name>INfc</name>\n"
+ " <instance>default</instance>\n"
+ " </interface>\n"
+ " </hal>\n"
+ " <sepolicy>\n"
+ " <version>25.0</version>\n"
+ " </sepolicy>\n"
+ " <xmlfile>\n"
+ " <name>media_profile</name>\n"
+ " <version>1.0</version>\n"
+ " </xmlfile>\n"
+ "</manifest>\n");
+ HalManifest vm2;
+ EXPECT_TRUE(gHalManifestConverter(&vm2, xml));
+ EXPECT_EQ(vm, vm2);
+}
+
+TEST_F(LibVintfTest, CompatibilityMatrixConverterXmlFile) {
+ CompatibilityMatrix cm;
+ addXmlFile(cm, "media_profile", {1, 0});
+ std::string xml = gCompatibilityMatrixConverter(cm);
+ EXPECT_EQ(xml,
+ "<compatibility-matrix version=\"1.0\" type=\"framework\">\n"
+ " <sepolicy>\n"
+ " <kernel-sepolicy-version>0</kernel-sepolicy-version>\n"
+ " </sepolicy>\n"
+ " <avb>\n"
+ " <vbmeta-version>0.0</vbmeta-version>\n"
+ " </avb>\n"
+ " <xmlfile format=\"dtd\" optional=\"true\">\n"
+ " <name>media_profile</name>\n"
+ " <version>1.0</version>\n"
+ " </xmlfile>\n"
+ "</compatibility-matrix>\n");
+ CompatibilityMatrix cm2;
+ EXPECT_TRUE(gCompatibilityMatrixConverter(&cm2, xml));
+ EXPECT_EQ(cm, cm2);
+}
+
+TEST_F(LibVintfTest, CompatibilityMatrixConverterXmlFile2) {
+ std::string xml =
+ "<compatibility-matrix version=\"1.0\" type=\"framework\">\n"
+ " <xmlfile format=\"dtd\" optional=\"false\">\n"
+ " <name>media_profile</name>\n"
+ " <version>1.0</version>\n"
+ " </xmlfile>\n"
+ "</compatibility-matrix>\n";
+ CompatibilityMatrix cm;
+ EXPECT_FALSE(gCompatibilityMatrixConverter(&cm, xml));
+ EXPECT_EQ(
+ "compatibility-matrix.xmlfile entry media_profile has to be optional for "
+ "compatibility matrix version 1.0",
+ gCompatibilityMatrixConverter.lastError());
+}
+
} // namespace vintf
} // namespace android