Complete definition for CompatibilityMatrix

* Add KernelConfigTypedValue to CompatibilityMatrix
  to support KV pair in kernel information. config items
  in /proc/config.gz are more than just a string; they have
  the format:
    CONFIG_FOO=y
    CONFIG_BAR=""
    CONFIG_BAZ=0x99
  etc. Compatibility matrix needs to match the value part
  as well.

* Added minlts to each kernel entry. This allows
  KernelInfo::checkCompatibility to check if the current
  LTS version can support the framework.

Test: libvintf_test

Change-Id: I859829dee8fdee0d856c33c1f5836d8c9c94099a
diff --git a/parse_xml.cpp b/parse_xml.cpp
index 21e7480..328de3d 100644
--- a/parse_xml.cpp
+++ b/parse_xml.cpp
@@ -294,12 +294,50 @@
 const XmlTextConverter<VersionRange> versionRangeConverter{"version"};
 const XmlConverter<VersionRange> &gVersionRangeConverter = versionRangeConverter;
 
-const XmlTextConverter<KernelConfig> kernelConfigConverter{"config"};
-const XmlConverter<KernelConfig> &gKernelConfigConverter = kernelConfigConverter;
-
 const XmlTextConverter<Transport> transportConverter{"transport"};
 const XmlConverter<Transport> &gTransportConverter = transportConverter;
 
+const XmlTextConverter<KernelConfigKey> kernelConfigKeyConverter{"key"};
+
+struct KernelConfigTypedValueConverter : public XmlNodeConverter<KernelConfigTypedValue> {
+    std::string elementName() const override { return "value"; }
+    void mutateNode(const KernelConfigTypedValue &object, NodeType *root, DocType *d) const override {
+        appendAttr(root, "type", object.mType);
+        appendText(root, ::android::vintf::to_string(object), d);
+    }
+    bool buildObject(KernelConfigTypedValue *object, NodeType *root) const override {
+        std::string stringValue;
+        if (!parseAttr(root, "type", &object->mType) ||
+            !parseText(root, &stringValue)) {
+            return false;
+        }
+        if (!::android::vintf::parseKernelConfigValue(stringValue, object)) {
+            return false;
+        }
+        return true;
+    }
+};
+
+const KernelConfigTypedValueConverter kernelConfigTypedValueConverter{};
+const XmlConverter<KernelConfigTypedValue> &gKernelConfigTypedValueConverter = 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) const override {
+        if (   !parseChild(root, kernelConfigKeyConverter, &object->first)
+            || !parseChild(root, kernelConfigTypedValueConverter, &object->second)) {
+            return false;
+        }
+        return true;
+    }
+};
+
+const KernelConfigConverter kernelConfigConverter{};
+
 struct MatrixHalConverter : public XmlNodeConverter<MatrixHal> {
     std::string elementName() const override { return "hal"; }
     void mutateNode(const MatrixHal &hal, NodeType *root, DocType *d) const override {
@@ -327,14 +365,20 @@
 struct MatrixKernelConverter : public XmlNodeConverter<MatrixKernel> {
     std::string elementName() const override { return "kernel"; }
     void mutateNode(const MatrixKernel &kernel, NodeType *root, DocType *d) const override {
-        appendAttr(root, "version", kernel.version);
-        for (const auto &config : kernel.configs) {
+        appendAttr(root, "version", Version{kernel.mMinLts.version, kernel.mMinLts.majorRev});
+        appendAttr(root, "minlts", kernel.mMinLts);
+        for (const KernelConfig &config : kernel.mConfigs) {
             appendChild(root, kernelConfigConverter(config, d));
         }
     }
     bool buildObject(MatrixKernel *object, NodeType *root) const override {
-        if (   !parseAttr(root, "version", &object->version)
-            || !parseChildren(root, kernelConfigConverter, &object->configs)) {
+        Version v;
+        if (   !parseAttr(root, "minlts", &object->mMinLts)
+            || !parseAttr(root, "version", &v)
+            || !parseChildren(root, kernelConfigConverter, &object->mConfigs)) {
+            return false;
+        }
+        if (v != Version{object->mMinLts.version, object->mMinLts.majorRev}) {
             return false;
         }
         return true;