Allow KernelInfo to be (de)serialized.
Test: libvintf_test
Bug: 111125947
Change-Id: If63fd9354afa1a818f1b866d8d7ac0306bd15cfd
diff --git a/include/vintf/KernelInfo.h b/include/vintf/KernelInfo.h
index 556b768..620883f 100644
--- a/include/vintf/KernelInfo.h
+++ b/include/vintf/KernelInfo.h
@@ -50,6 +50,7 @@
private:
friend class details::MockRuntimeInfo;
+ friend struct KernelInfoConverter;
friend struct LibVintfTest;
friend struct RuntimeInfoFetcher;
// x.y.z
diff --git a/parse_xml.cpp b/parse_xml.cpp
index 0cc514d..6498012 100644
--- a/parse_xml.cpp
+++ b/parse_xml.cpp
@@ -345,8 +345,9 @@
return true;
}
- template <typename T>
- inline bool parseChildren(NodeType* root, const XmlNodeConverter<T>& conv, std::set<T>* s,
+ template <typename Container, typename T = typename Container::value_type,
+ typename = typename Container::key_compare>
+ inline bool parseChildren(NodeType* root, const XmlNodeConverter<T>& conv, Container* s,
std::string* error) const {
std::vector<T> vec;
if (!parseChildren(root, conv, &vec, error)) {
@@ -363,6 +364,12 @@
return true;
}
+ template <typename K, typename V>
+ inline bool parseChildren(NodeType* root, const XmlNodeConverter<std::pair<K, V>>& conv,
+ std::map<K, V>* s, std::string* error) const {
+ return parseChildren<std::map<K, V>, std::pair<K, V>>(root, conv, s, error);
+ }
+
inline bool parseText(NodeType* node, std::string* s, std::string* /* error */) const {
*s = getText(node);
return true;
@@ -399,14 +406,38 @@
std::string mElementName;
};
+template <typename Pair>
+struct XmlPairConverter : public XmlNodeConverter<Pair> {
+ XmlPairConverter(
+ const std::string& elementName,
+ std::unique_ptr<XmlNodeConverter<typename Pair::first_type>>&& firstConverter,
+ std::unique_ptr<XmlNodeConverter<typename Pair::second_type>>&& secondConverter)
+ : mElementName(elementName),
+ mFirstConverter(std::move(firstConverter)),
+ mSecondConverter(std::move(secondConverter)) {}
+
+ virtual void mutateNode(const Pair& pair, NodeType* root, DocType* d) const override {
+ appendChild(root, mFirstConverter->serialize(pair.first, d));
+ appendChild(root, mSecondConverter->serialize(pair.second, d));
+ }
+ virtual bool buildObject(Pair* pair, NodeType* root, std::string* error) const override {
+ return this->parseChild(root, *mFirstConverter, &pair->first, error) &&
+ this->parseChild(root, *mSecondConverter, &pair->second, error);
+ }
+ virtual std::string elementName() const { return mElementName; }
+
+ private:
+ std::string mElementName;
+ std::unique_ptr<XmlNodeConverter<typename Pair::first_type>> mFirstConverter;
+ std::unique_ptr<XmlNodeConverter<typename Pair::second_type>> mSecondConverter;
+};
+
// ---------------------- XmlNodeConverter definitions end
XmlTextConverter<Version> versionConverter{"version"};
XmlTextConverter<VersionRange> versionRangeConverter{"version"};
-XmlTextConverter<KernelConfigKey> kernelConfigKeyConverter{"key"};
-
struct TransportArchConverter : public XmlNodeConverter<TransportArch> {
std::string elementName() const override { return "transport"; }
void mutateNode(const TransportArch &object, NodeType *root, DocType *d) const override {
@@ -455,22 +486,9 @@
KernelConfigTypedValueConverter kernelConfigTypedValueConverter{};
-struct KernelConfigConverter : public XmlNodeConverter<KernelConfig> {
- std::string elementName() const override { return "config"; }
- void mutateNode(const KernelConfig &object, NodeType *root, DocType *d) const override {
- appendChild(root, kernelConfigKeyConverter(object.first, d));
- appendChild(root, kernelConfigTypedValueConverter(object.second, d));
- }
- bool buildObject(KernelConfig* object, NodeType* root, std::string* error) const override {
- if (!parseChild(root, kernelConfigKeyConverter, &object->first, error) ||
- !parseChild(root, kernelConfigTypedValueConverter, &object->second, error)) {
- return false;
- }
- return true;
- }
-};
-
-KernelConfigConverter kernelConfigConverter{};
+XmlPairConverter<KernelConfig> matrixKernelConfigConverter{
+ "config", std::make_unique<XmlTextConverter<KernelConfigKey>>("key"),
+ std::make_unique<KernelConfigTypedValueConverter>(kernelConfigTypedValueConverter)};
struct HalInterfaceConverter : public XmlNodeConverter<HalInterface> {
std::string elementName() const override { return "interface"; }
@@ -589,11 +607,11 @@
std::string elementName() const override { return "conditions"; }
void mutateNode(const std::vector<KernelConfig>& conds, NodeType* root,
DocType* d) const override {
- appendChildren(root, kernelConfigConverter, conds, d);
+ appendChildren(root, matrixKernelConfigConverter, conds, d);
}
bool buildObject(std::vector<KernelConfig>* object, NodeType* root,
std::string* error) const override {
- return parseChildren(root, kernelConfigConverter, object, error);
+ return parseChildren(root, matrixKernelConfigConverter, object, error);
}
};
@@ -616,14 +634,14 @@
appendChild(root, matrixKernelConditionsConverter(kernel.mConditions, d));
}
if (flags.isKernelConfigsEnabled()) {
- appendChildren(root, kernelConfigConverter, kernel.mConfigs, d);
+ appendChildren(root, matrixKernelConfigConverter, kernel.mConfigs, d);
}
}
bool buildObject(MatrixKernel* object, NodeType* root, std::string* error) const override {
if (!parseAttr(root, "version", &object->mMinLts, error) ||
!parseOptionalChild(root, matrixKernelConditionsConverter, {}, &object->mConditions,
error) ||
- !parseChildren(root, kernelConfigConverter, &object->mConfigs, error)) {
+ !parseChildren(root, matrixKernelConfigConverter, &object->mConfigs, error)) {
return false;
}
return true;
@@ -858,6 +876,32 @@
};
ManifestXmlFileConverter manifestXmlFileConverter{};
+XmlPairConverter<std::pair<std::string, std::string>> kernelConfigConverter{
+ "config", std::make_unique<XmlTextConverter<std::string>>("key"),
+ std::make_unique<XmlTextConverter<std::string>>("value")};
+
+struct KernelInfoConverter : public XmlNodeConverter<KernelInfo> {
+ std::string elementName() const override { return "kernel"; }
+ void mutateNode(const KernelInfo& o, NodeType* root, DocType* d) const override {
+ mutateNode(o, root, d, SerializeFlags::EVERYTHING);
+ }
+ void mutateNode(const KernelInfo& o, NodeType* root, DocType* d,
+ SerializeFlags::Type flags) const override {
+ if (o.version() != KernelVersion{}) {
+ appendAttr(root, "version", o.version());
+ }
+ if (flags.isKernelConfigsEnabled()) {
+ appendChildren(root, kernelConfigConverter, o.configs(), d);
+ }
+ }
+ bool buildObject(KernelInfo* o, NodeType* root, std::string* error) const override {
+ return parseOptionalAttr(root, "version", {}, &o->mVersion, error) &&
+ parseChildren(root, kernelConfigConverter, &o->mConfigs, error);
+ }
+};
+
+KernelInfoConverter kernelInfoConverter{};
+
struct HalManifestConverter : public XmlNodeConverter<HalManifest> {
std::string elementName() const override { return "manifest"; }
void mutateNode(const HalManifest &m, NodeType *root, DocType *d) const override {
@@ -1189,6 +1233,7 @@
kernelConfigTypedValueConverter;
XmlConverter<MatrixHal>& gMatrixHalConverter = matrixHalConverter;
XmlConverter<ManifestHal>& gManifestHalConverter = manifestHalConverter;
+XmlConverter<KernelInfo>& gKernelInfoConverter = kernelInfoConverter;
} // namespace vintf
} // namespace android
diff --git a/test/LibVintfTest.cpp b/test/LibVintfTest.cpp
index afd602e..f5690aa 100644
--- a/test/LibVintfTest.cpp
+++ b/test/LibVintfTest.cpp
@@ -37,6 +37,7 @@
extern XmlConverter<ManifestHal>& gManifestHalConverter;
extern XmlConverter<MatrixHal>& gMatrixHalConverter;
extern XmlConverter<KernelConfigTypedValue>& gKernelConfigTypedValueConverter;
+extern XmlConverter<KernelInfo>& gKernelInfoConverter;
extern XmlConverter<HalManifest>& gHalManifestConverter;
extern XmlConverter<CompatibilityMatrix>& gCompatibilityMatrixConverter;
@@ -186,15 +187,20 @@
info.mOsVersion = "#4 SMP PREEMPT Wed Feb 1 18:10:52 PST 2017";
info.mHardwareId = "aarch64";
info.mKernelSepolicyVersion = 30;
- info.mKernel.mVersion = {3, 18, 31};
- info.mKernel.mConfigs = {{"CONFIG_64BIT", "y"},
- {"CONFIG_ANDROID_BINDER_DEVICES", "\"binder,hwbinder\""},
- {"CONFIG_ARCH_MMAP_RND_BITS", "24"},
- {"CONFIG_BUILD_ARM64_APPENDED_DTB_IMAGE_NAMES", "\"\""},
- {"CONFIG_ILLEGAL_POINTER_VALUE", "0xdead000000000000"}};
+ info.mKernel = testKernelInfo();
setAvb(info, {2, 1}, {2, 1});
return info;
}
+ KernelInfo testKernelInfo() {
+ KernelInfo info;
+ info.mVersion = {3, 18, 31};
+ info.mConfigs = {{"CONFIG_64BIT", "y"},
+ {"CONFIG_ANDROID_BINDER_DEVICES", "\"binder,hwbinder\""},
+ {"CONFIG_ARCH_MMAP_RND_BITS", "24"},
+ {"CONFIG_BUILD_ARM64_APPENDED_DTB_IMAGE_NAMES", "\"\""},
+ {"CONFIG_ILLEGAL_POINTER_VALUE", "0xdead000000000000"}};
+ return info;
+ }
};
TEST_F(LibVintfTest, ArchOperatorOr) {
@@ -3440,6 +3446,35 @@
std::set<std::string>({"android.hardware.camera@2.0", "android.hardware.nfc@1.0"}));
}
+TEST_F(LibVintfTest, KernelInfo) {
+ KernelInfo ki = testKernelInfo();
+
+ EXPECT_EQ(
+ "<kernel version=\"3.18.31\">\n"
+ " <config>\n"
+ " <key>CONFIG_64BIT</key>\n"
+ " <value>y</value>\n"
+ " </config>\n"
+ " <config>\n"
+ " <key>CONFIG_ANDROID_BINDER_DEVICES</key>\n"
+ " <value>\"binder,hwbinder\"</value>\n"
+ " </config>\n"
+ " <config>\n"
+ " <key>CONFIG_ARCH_MMAP_RND_BITS</key>\n"
+ " <value>24</value>\n"
+ " </config>\n"
+ " <config>\n"
+ " <key>CONFIG_BUILD_ARM64_APPENDED_DTB_IMAGE_NAMES</key>\n"
+ " <value>\"\"</value>\n"
+ " </config>\n"
+ " <config>\n"
+ " <key>CONFIG_ILLEGAL_POINTER_VALUE</key>\n"
+ " <value>0xdead000000000000</value>\n"
+ " </config>\n"
+ "</kernel>\n",
+ gKernelInfoConverter(ki, SerializeFlags::NO_TAGS.enableKernelConfigs()));
+}
+
} // namespace vintf
} // namespace android