Merge "Add android::fs_mgr namespace for new Fstab code"
diff --git a/Android.bp b/Android.bp
index 4689832..1ff4812 100644
--- a/Android.bp
+++ b/Android.bp
@@ -45,6 +45,7 @@
         "HalInterface.cpp",
         "KernelConfigTypedValue.cpp",
         "KernelConfigParser.cpp",
+        "KernelInfo.cpp",
         "RuntimeInfo.cpp",
         "ManifestHal.cpp",
         "ManifestInstance.cpp",
diff --git a/AssembleVintf.cpp b/AssembleVintf.cpp
index 2353216..bcefc73 100644
--- a/AssembleVintf.cpp
+++ b/AssembleVintf.cpp
@@ -206,13 +206,7 @@
     static bool parseFileForKernelConfigs(std::basic_istream<char>& stream,
                                           std::vector<KernelConfig>* out) {
         KernelConfigParser parser(true /* processComments */, true /* relaxedFormat */);
-        std::string content = read(stream);
-        status_t err = parser.process(content.c_str(), content.size());
-        if (err != OK) {
-            std::cerr << parser.error();
-            return false;
-        }
-        err = parser.finish();
+        status_t err = parser.processAndFinish(read(stream));
         if (err != OK) {
             std::cerr << parser.error();
             return false;
@@ -314,6 +308,36 @@
         out() << "-->" << std::endl;
     }
 
+    // Parse --kernel arguments and write to output manifest.
+    bool setDeviceManifestKernel(HalManifest* manifest) {
+        if (mKernels.empty()) {
+            return true;
+        }
+        if (mKernels.size() > 1) {
+            std::cerr << "Warning: multiple --kernel is specified when building device manifest. "
+                      << "Only the first one will be used." << std::endl;
+        }
+        auto& kernelArg = *mKernels.begin();
+        const auto& kernelVer = kernelArg.first;
+        auto& kernelConfigFiles = kernelArg.second;
+        // addKernel() guarantees that !kernelConfigFiles.empty().
+        if (kernelConfigFiles.size() > 1) {
+            std::cerr << "Warning: multiple config files are specified in --kernel when building "
+                      << "device manfiest. Only the first one will be used." << std::endl;
+        }
+
+        KernelConfigParser parser(true /* processComments */, false /* relaxedFormat */);
+        status_t err = parser.processAndFinish(read(kernelConfigFiles[0].stream()));
+        if (err != OK) {
+            std::cerr << parser.error();
+            return false;
+        }
+        manifest->device.mKernel = std::make_optional<KernelInfo>();
+        manifest->device.mKernel->mVersion = kernelVer;
+        manifest->device.mKernel->mConfigs = parser.configs();
+        return true;
+    }
+
     bool assembleHalManifest(HalManifests* halManifests) {
         std::string error;
         HalManifest* halManifest = &halManifests->front().object;
@@ -364,6 +388,10 @@
             if (!setDeviceFcmVersion(halManifest)) {
                 return false;
             }
+
+            if (!setDeviceManifestKernel(halManifest)) {
+                return false;
+            }
         }
 
         if (halManifest->mType == SchemaType::FRAMEWORK) {
diff --git a/HalManifest.cpp b/HalManifest.cpp
index b795136..d844c4c 100644
--- a/HalManifest.cpp
+++ b/HalManifest.cpp
@@ -317,20 +317,24 @@
             return false;
         }
     } else if (mType == SchemaType::DEVICE) {
-        bool match = false;
+        bool sepolicyMatch = false;
         for (const auto &range : mat.framework.mSepolicy.sepolicyVersions()) {
             if (range.supportedBy(device.mSepolicyVersion)) {
-                match = true;
+                sepolicyMatch = true;
                 break;
             }
         }
-        if (!match) {
+        if (!sepolicyMatch) {
             if (error != nullptr) {
                 *error = "Sepolicy version " + to_string(device.mSepolicyVersion)
                         + " doesn't satisify the requirements.";
             }
             return false;
         }
+
+        if (!!kernel() && !kernel()->matchKernelRequirements(mat.framework.mKernels, error)) {
+            return false;
+        }
     }
 
     return true;
@@ -413,7 +417,8 @@
     return lft.mType == rgt.mType && lft.mLevel == rgt.mLevel && lft.mHals == rgt.mHals &&
            lft.mXmlFiles == rgt.mXmlFiles &&
            (lft.mType != SchemaType::DEVICE ||
-            (lft.device.mSepolicyVersion == rgt.device.mSepolicyVersion)) &&
+            (lft.device.mSepolicyVersion == rgt.device.mSepolicyVersion &&
+             lft.device.mKernel == rgt.device.mKernel)) &&
            (lft.mType != SchemaType::FRAMEWORK ||
             (
 #pragma clang diagnostic push
@@ -470,5 +475,9 @@
     return (*this) == emptyManifest;
 }
 
+const std::optional<KernelInfo>& HalManifest::kernel() const {
+    return device.mKernel;
+}
+
 } // namespace vintf
 } // namespace android
diff --git a/KernelConfigParser.cpp b/KernelConfigParser.cpp
index a0955e2..5713f22 100644
--- a/KernelConfigParser.cpp
+++ b/KernelConfigParser.cpp
@@ -133,5 +133,17 @@
     return err;
 }
 
+status_t KernelConfigParser::processAndFinish(const char* buf, size_t len) {
+    status_t err = process(buf, len);
+    if (err != OK) {
+        return err;
+    }
+    return finish();
+}
+
+status_t KernelConfigParser::processAndFinish(const std::string& content) {
+    return processAndFinish(content.c_str(), content.size());
+}
+
 }  // namespace vintf
 }  // namespace android
diff --git a/KernelInfo.cpp b/KernelInfo.cpp
new file mode 100644
index 0000000..1a37bdf
--- /dev/null
+++ b/KernelInfo.cpp
@@ -0,0 +1,110 @@
+/*
+ * Copyright (C) 2019 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 "KernelInfo.h"
+
+#include "parse_string.h"
+
+namespace android {
+namespace vintf {
+
+const KernelVersion& KernelInfo::version() const {
+    return mVersion;
+}
+
+const std::map<std::string, std::string>& KernelInfo::configs() const {
+    return mConfigs;
+}
+
+bool KernelInfo::matchKernelConfigs(const std::vector<KernelConfig>& matrixConfigs,
+                                    std::string* error) const {
+    for (const KernelConfig& matrixConfig : matrixConfigs) {
+        const std::string& key = matrixConfig.first;
+        auto it = this->mConfigs.find(key);
+        if (it == this->mConfigs.end()) {
+            // special case: <value type="tristate">n</value> matches if the config doesn't exist.
+            if (matrixConfig.second == KernelConfigTypedValue::gMissingConfig) {
+                continue;
+            }
+            if (error != nullptr) {
+                *error = "Missing config " + key;
+            }
+            return false;
+        }
+        const std::string& kernelValue = it->second;
+        if (!matrixConfig.second.matchValue(kernelValue)) {
+            if (error != nullptr) {
+                *error = "For config " + key + ", value = " + kernelValue + " but required " +
+                         to_string(matrixConfig.second);
+            }
+            return false;
+        }
+    }
+    return true;
+}
+
+bool KernelInfo::matchKernelVersion(const KernelVersion& minLts) const {
+    return minLts.version == mVersion.version && minLts.majorRev == mVersion.majorRev &&
+           minLts.minorRev <= mVersion.minorRev;
+}
+
+bool KernelInfo::matchKernelRequirements(const std::vector<MatrixKernel>& kernels,
+                                         std::string* error) const {
+    bool foundMatchedKernelVersion = false;
+    bool foundMatchedConditions = false;
+    for (const MatrixKernel& matrixKernel : kernels) {
+        if (!matchKernelVersion(matrixKernel.minLts())) {
+            continue;
+        }
+        foundMatchedKernelVersion = true;
+        // ignore this fragment if not all conditions are met.
+        if (!matchKernelConfigs(matrixKernel.conditions(), error)) {
+            continue;
+        }
+        foundMatchedConditions = true;
+        if (!matchKernelConfigs(matrixKernel.configs(), error)) {
+            return false;
+        }
+    }
+    if (!foundMatchedKernelVersion) {
+        if (error != nullptr) {
+            std::stringstream ss;
+            ss << "Framework is incompatible with kernel version " << version()
+               << ", compatible kernel versions are";
+            for (const MatrixKernel& matrixKernel : kernels) ss << " " << matrixKernel.minLts();
+            *error = ss.str();
+        }
+        return false;
+    }
+    if (!foundMatchedConditions) {
+        // This should not happen because first <conditions> for each <kernel> must be
+        // empty. Reject here for inconsistency.
+        if (error != nullptr) {
+            error->insert(0, "Framework match kernel version with unmet conditions:");
+        }
+        return false;
+    }
+    if (error != nullptr) {
+        error->clear();
+    }
+    return true;
+}
+
+bool KernelInfo::operator==(const KernelInfo& other) const {
+    return mVersion == other.mVersion && mConfigs == other.mConfigs;
+}
+
+}  // namespace vintf
+}  // namespace android
diff --git a/RuntimeInfo-target.cpp b/RuntimeInfo-target.cpp
index 6f2e9e8..d221897 100644
--- a/RuntimeInfo-target.cpp
+++ b/RuntimeInfo-target.cpp
@@ -80,7 +80,7 @@
     }
     mConfigParser.finish();
     gzclose(f);
-    mRuntimeInfo->mKernelConfigs = std::move(mConfigParser.configs());
+    mRuntimeInfo->mKernel.mConfigs = std::move(mConfigParser.configs());
     return err;
 }
 
@@ -141,7 +141,7 @@
     }
     pos = mRuntimeInfo->mOsRelease.find_first_not_of("0123456789", pos + 1);
     // no need to check pos == std::string::npos, because substr will handle this
-    if (!parse(mRuntimeInfo->mOsRelease.substr(0, pos), &mRuntimeInfo->mKernelVersion)) {
+    if (!parse(mRuntimeInfo->mOsRelease.substr(0, pos), &mRuntimeInfo->mKernel.mVersion)) {
         return UNKNOWN_ERROR;
     }
     return OK;
diff --git a/RuntimeInfo.cpp b/RuntimeInfo.cpp
index 2338cd2..86f021c 100644
--- a/RuntimeInfo.cpp
+++ b/RuntimeInfo.cpp
@@ -46,11 +46,11 @@
 }
 
 const KernelVersion &RuntimeInfo::kernelVersion() const {
-    return mKernelVersion;
+    return mKernel.version();
 }
 
 const std::map<std::string, std::string> &RuntimeInfo::kernelConfigs() const {
-    return mKernelConfigs;
+    return mKernel.configs();
 }
 
 size_t RuntimeInfo::kernelSepolicyVersion() const {
@@ -69,38 +69,6 @@
     return mBootAvbVersion;
 }
 
-bool RuntimeInfo::matchKernelConfigs(const std::vector<KernelConfig>& matrixConfigs,
-                                     std::string* error) const {
-    for (const KernelConfig& matrixConfig : matrixConfigs) {
-        const std::string& key = matrixConfig.first;
-        auto it = this->mKernelConfigs.find(key);
-        if (it == this->mKernelConfigs.end()) {
-            // special case: <value type="tristate">n</value> matches if the config doesn't exist.
-            if (matrixConfig.second == KernelConfigTypedValue::gMissingConfig) {
-                continue;
-            }
-            if (error != nullptr) {
-                *error = "Missing config " + key;
-            }
-            return false;
-        }
-        const std::string& kernelValue = it->second;
-        if (!matrixConfig.second.matchValue(kernelValue)) {
-            if (error != nullptr) {
-                *error = "For config " + key + ", value = " + kernelValue + " but required " +
-                         to_string(matrixConfig.second);
-            }
-            return false;
-        }
-    }
-    return true;
-}
-
-bool RuntimeInfo::matchKernelVersion(const KernelVersion& minLts) const {
-    return minLts.version == mKernelVersion.version && minLts.majorRev == mKernelVersion.majorRev &&
-           minLts.minorRev <= mKernelVersion.minorRev;
-}
-
 bool RuntimeInfo::checkCompatibility(const CompatibilityMatrix& mat, std::string* error,
                                      CheckFlags::Type flags) const {
     if (mat.mType != SchemaType::FRAMEWORK) {
@@ -123,44 +91,9 @@
     // HalManifest.device.mSepolicyVersion in HalManifest::checkCompatibility.
 
     if (flags.isKernelEnabled()) {
-        bool foundMatchedKernelVersion = false;
-        bool foundMatchedConditions = false;
-        for (const MatrixKernel& matrixKernel : mat.framework.mKernels) {
-            if (!matchKernelVersion(matrixKernel.minLts())) {
-                continue;
-            }
-            foundMatchedKernelVersion = true;
-            // ignore this fragment if not all conditions are met.
-            if (!matchKernelConfigs(matrixKernel.conditions(), error)) {
-                continue;
-            }
-            foundMatchedConditions = true;
-            if (!matchKernelConfigs(matrixKernel.configs(), error)) {
-                return false;
-            }
-        }
-        if (!foundMatchedKernelVersion) {
-            if (error != nullptr) {
-                std::stringstream ss;
-                ss << "Framework is incompatible with kernel version " << mKernelVersion
-                   << ", compatible kernel versions are";
-                for (const MatrixKernel& matrixKernel : mat.framework.mKernels)
-                    ss << " " << matrixKernel.minLts();
-                *error = ss.str();
-            }
+        if (!mKernel.matchKernelRequirements(mat.framework.mKernels, error)) {
             return false;
         }
-        if (!foundMatchedConditions) {
-            // This should not happen because first <conditions> for each <kernel> must be
-            // empty. Reject here for inconsistency.
-            if (error != nullptr) {
-                error->insert(0, "Framework match kernel version with unmet conditions:");
-            }
-            return false;
-        }
-        if (error != nullptr) {
-            error->clear();
-        }
     }
 
     if (flags.isAvbEnabled()) {
diff --git a/VintfObject.cpp b/VintfObject.cpp
index 1100977..fbe4045 100644
--- a/VintfObject.cpp
+++ b/VintfObject.cpp
@@ -548,9 +548,15 @@
         return INCOMPATIBLE;
     }
 
+    CheckFlags::Type runtimeInfoCheckFlags = flags;
+    if (!!getDeviceHalManifest()->kernel()) {
+        // Use kernel from incoming OTA package, but not on the device.
+        runtimeInfoCheckFlags = runtimeInfoCheckFlags.disableKernel();
+    }
+
     if (flags.isRuntimeInfoEnabled()) {
         if (!getRuntimeInfo()->checkCompatibility(*getFrameworkCompatibilityMatrix(), error,
-                                                  flags)) {
+                                                  runtimeInfoCheckFlags)) {
             if (error) {
                 error->insert(0,
                               "Runtime info and framework compatibility matrix are incompatible: ");
diff --git a/assemble_vintf_main.cpp b/assemble_vintf_main.cpp
index 2733261..b25a477 100644
--- a/assemble_vintf_main.cpp
+++ b/assemble_vintf_main.cpp
@@ -53,8 +53,11 @@
                  "               If any check fails, an error message is written to stderr.\n"
                  "               Return 1.\n"
                  "    --kernel=<version>:<android-base.config>[:<android-base-arch.config>[...]]\n"
-                 "               Add a kernel entry to framework compatibility matrix.\n"
-                 "               Ignored for other input format.\n"
+                 "               Add a kernel entry to framework compatibility matrix or device\n"
+                 "               manifest. Ignored for other input format.\n"
+                 "               There can be any number of --kernel for framework compatibility\n"
+                 "               matrix, but at most one --kernel and at most one config file for\n"
+                 "               device manifest.\n"
                  "               <version> has format: 3.18.0\n"
                  "               <android-base.config> is the location of android-base.config\n"
                  "               <android-base-arch.config> is the location of an optional\n"
diff --git a/include/vintf/CheckFlags.h b/include/vintf/CheckFlags.h
index 2da807c..52d35a7 100644
--- a/include/vintf/CheckFlags.h
+++ b/include/vintf/CheckFlags.h
@@ -25,9 +25,9 @@
 // Flags for *::checkCompatibility functions.
 class Type {
    public:
-#define VINTF_CHECK_FLAGS_FIELD(name, bit)                                      \
-    constexpr Type enable##name() const { return Type(mValue | (1 << bit)); }   \
-    constexpr Type disable##name() const { return Type(mValue & ~(1 << bit)); } \
+#define VINTF_CHECK_FLAGS_FIELD(name, bit)                                                    \
+    [[nodiscard]] constexpr Type enable##name() const { return Type(mValue | (1 << bit)); }   \
+    [[nodiscard]] constexpr Type disable##name() const { return Type(mValue & ~(1 << bit)); } \
     constexpr bool is##name##Enabled() const { return mValue & (1 << bit); }
 
     VINTF_CHECK_FLAGS_FIELD(Avb, 0)
diff --git a/include/vintf/HalManifest.h b/include/vintf/HalManifest.h
index 9b88c6a..1c90d17 100644
--- a/include/vintf/HalManifest.h
+++ b/include/vintf/HalManifest.h
@@ -20,11 +20,13 @@
 
 #include <utils/Errors.h>
 #include <map>
+#include <optional>
 #include <string>
 #include <vector>
 
 #include "FileSystem.h"
 #include "HalGroup.h"
+#include "KernelInfo.h"
 #include "Level.h"
 #include "ManifestHal.h"
 #include "ManifestInstance.h"
@@ -126,6 +128,9 @@
     bool insertInstance(const FqInstance& fqInstance, Transport transport, Arch arch, HalFormat fmt,
                         std::string* error = nullptr);
 
+    // Get the <kernel> tag. Assumes type() == DEVICE.
+    const std::optional<KernelInfo>& kernel() const;
+
    protected:
     // Check before add()
     bool shouldAdd(const ManifestHal& toAdd) const override;
@@ -172,6 +177,7 @@
     // entries for device hal manifest only
     struct {
         Version mSepolicyVersion;
+        std::optional<KernelInfo> mKernel;
     } device;
 
     // entries for framework hal manifest only
diff --git a/include/vintf/KernelConfigParser.h b/include/vintf/KernelConfigParser.h
index 06a034d..9d5a8fe 100644
--- a/include/vintf/KernelConfigParser.h
+++ b/include/vintf/KernelConfigParser.h
@@ -33,6 +33,8 @@
 
     status_t process(const char* buf, size_t len);
     status_t finish();
+    status_t processAndFinish(const char* buf, size_t len);
+    status_t processAndFinish(const std::string& content);
     std::stringbuf* error() const;
     std::map<std::string, std::string>& configs();
     const std::map<std::string, std::string>& configs() const;
diff --git a/include/vintf/KernelInfo.h b/include/vintf/KernelInfo.h
new file mode 100644
index 0000000..16bb2c3
--- /dev/null
+++ b/include/vintf/KernelInfo.h
@@ -0,0 +1,67 @@
+/*
+ * Copyright (C) 2019 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.
+ */
+
+#pragma once
+
+#include <map>
+#include <string>
+#include <vector>
+
+#include "MatrixKernel.h"
+#include "Version.h"
+
+namespace android {
+namespace vintf {
+
+namespace details {
+class MockRuntimeInfo;
+}  // namespace details
+
+// KernelInfo includes kernel-specific information on a device.
+class KernelInfo {
+   public:
+    KernelInfo() = default;
+
+    const KernelVersion& version() const;
+    const std::map<std::string, std::string>& configs() const;
+
+    // mVersion = x'.y'.z', minLts = x.y.z,
+    // match if x == x' , y == y' , and z <= z'.
+    bool matchKernelVersion(const KernelVersion& minLts) const;
+    // return true if all kernel configs in matrixConfigs matches.
+    bool matchKernelConfigs(const std::vector<KernelConfig>& matrixConfigs,
+                            std::string* error = nullptr) const;
+    // return true if this matches kernel requirement specified.
+    bool matchKernelRequirements(const std::vector<MatrixKernel>& kernels,
+                                 std::string* error = nullptr) const;
+
+    bool operator==(const KernelInfo& other) const;
+
+   private:
+    friend class AssembleVintfImpl;
+    friend class details::MockRuntimeInfo;
+    friend struct KernelInfoConverter;
+    friend struct LibVintfTest;
+    friend struct RuntimeInfoFetcher;
+    // x.y.z
+    KernelVersion mVersion;
+    // /proc/config.gz
+    // Key: CONFIG_xxx; Value: the value after = sign.
+    std::map<std::string, std::string> mConfigs;
+};
+
+}  // namespace vintf
+}  // namespace android
diff --git a/include/vintf/RuntimeInfo.h b/include/vintf/RuntimeInfo.h
index 2e04279..61a9b23 100644
--- a/include/vintf/RuntimeInfo.h
+++ b/include/vintf/RuntimeInfo.h
@@ -26,6 +26,7 @@
 #include <utils/Errors.h>
 
 #include "CheckFlags.h"
+#include "KernelInfo.h"
 #include "MatrixKernel.h"
 #include "Version.h"
 
@@ -96,22 +97,14 @@
     friend struct LibVintfTest;
     friend std::string dump(const RuntimeInfo& ki, bool);
 
-    // mKernelVersion = x'.y'.z', minLts = x.y.z,
-    // match if x == x' , y == y' , and z <= z'.
-    bool matchKernelVersion(const KernelVersion& minLts) const;
-    // return true if all kernel configs in matrixConfigs matches.
-    bool matchKernelConfigs(const std::vector<KernelConfig>& matrixConfigs,
-                            std::string* error = nullptr) const;
-
     // /proc/config.gz
     // Key: CONFIG_xxx; Value: the value after = sign.
-    std::map<std::string, std::string> mKernelConfigs;
+    KernelInfo mKernel;
     std::string mOsName;
     std::string mNodeName;
     std::string mOsRelease;
     std::string mOsVersion;
     std::string mHardwareId;
-    KernelVersion mKernelVersion;
 
     std::vector<std::string> mSepolicyFilePaths;
     std::string mCpuInfo;
diff --git a/parse_string.cpp b/parse_string.cpp
index e3310f3..1c6f3b8 100644
--- a/parse_string.cpp
+++ b/parse_string.cpp
@@ -469,10 +469,10 @@
         oss << "\n\ncpu info:\n" << ki.cpuInfo();
     }
 
-    oss << "\n#CONFIG's loaded = " << ki.mKernelConfigs.size() << ";\n";
+    oss << "\n#CONFIG's loaded = " << ki.kernelConfigs().size() << ";\n";
 
     if (verbose) {
-        for (const auto& pair : ki.mKernelConfigs) {
+        for (const auto& pair : ki.kernelConfigs()) {
             oss << pair.first << "=" << pair.second << "\n";
         }
     }
diff --git a/parse_xml.cpp b/parse_xml.cpp
index 0cc514d..fee7ba6 100644
--- a/parse_xml.cpp
+++ b/parse_xml.cpp
@@ -331,6 +331,18 @@
     }
 
     template <typename T>
+    inline bool parseOptionalChild(NodeType* root, const XmlNodeConverter<T>& conv,
+                                   std::optional<T>* t, std::string* error) const {
+        NodeType* child = getChild(root, conv.elementName());
+        if (child == nullptr) {
+            *t = std::nullopt;
+            return true;
+        }
+        *t = std::make_optional<T>();
+        return conv.deserialize(&**t, child, error);
+    }
+
+    template <typename T>
     inline bool parseChildren(NodeType* root, const XmlNodeConverter<T>& conv, std::vector<T>* v,
                               std::string* error) const {
         auto nodes = getChildren(root, conv.elementName());
@@ -345,8 +357,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 +376,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 +418,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 +498,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 +619,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 +646,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 +888,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 {
@@ -884,6 +940,12 @@
             if (m.mLevel != Level::UNSPECIFIED) {
                 this->appendAttr(root, "target-level", m.mLevel);
             }
+
+            if (flags.isKernelEnabled()) {
+                if (!!m.kernel()) {
+                    appendChild(root, kernelInfoConverter.serialize(*m.kernel(), d, flags));
+                }
+            }
         } else if (m.mType == SchemaType::FRAMEWORK) {
             if (flags.isVndkEnabled()) {
 #pragma clang diagnostic push
@@ -929,6 +991,10 @@
                                    error)) {
                 return false;
             }
+
+            if (!parseOptionalChild(root, kernelInfoConverter, &object->device.mKernel, error)) {
+                return false;
+            }
         } else if (object->mType == SchemaType::FRAMEWORK) {
 #pragma clang diagnostic push
 #pragma clang diagnostic ignored "-Wdeprecated-declarations"
@@ -1189,6 +1255,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 49a3a84..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;
 
@@ -183,20 +184,23 @@
         info.mOsName = "Linux";
         info.mNodeName = "localhost";
         info.mOsRelease = "3.18.31-g936f9a479d0f";
-        info.mKernelVersion = {3, 18, 31};
         info.mOsVersion = "#4 SMP PREEMPT Wed Feb 1 18:10:52 PST 2017";
         info.mHardwareId = "aarch64";
         info.mKernelSepolicyVersion = 30;
-        info.mKernelConfigs = {
-            {"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) {
@@ -3442,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
 
diff --git a/test/RuntimeInfo-fake.cpp b/test/RuntimeInfo-fake.cpp
index 0efcae7..8ee8305 100644
--- a/test/RuntimeInfo-fake.cpp
+++ b/test/RuntimeInfo-fake.cpp
@@ -27,15 +27,15 @@
     mOsName = "Linux";
     mNodeName = "localhost";
     mOsRelease = "3.18.31-g936f9a479d0f";
-    mKernelVersion = {3, 18, 31};
     mOsVersion = "#4 SMP PREEMPT Wed Feb 1 18:10:52 PST 2017";
     mHardwareId = "aarch64";
     mKernelSepolicyVersion = 30;
-    mKernelConfigs = {{"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"}};
+    mKernel.mVersion = {3, 18, 31};
+    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"}};
 
     return OK;
 }
diff --git a/test/vintf_object_tests.cpp b/test/vintf_object_tests.cpp
index 92e2ce9..f97d81f 100644
--- a/test/vintf_object_tests.cpp
+++ b/test/vintf_object_tests.cpp
@@ -327,6 +327,27 @@
     "    </hal>\n"
     "</manifest>\n";
 
+//
+// Set of metadata for kernel requirements
+//
+
+const std::string vendorManifestKernel318 =
+    "<manifest version=\"1.0\" type=\"device\">\n"
+    "    <kernel version=\"3.18.999\" />\n"
+    "    <sepolicy>\n"
+    "        <version>25.5</version>\n"
+    "    </sepolicy>\n"
+    "</manifest>\n";
+
+const std::string systemMatrixKernel318 =
+    "<compatibility-matrix version=\"1.0\" type=\"framework\">\n"
+    "    <kernel version=\"3.18.999\"></kernel>\n"
+    "    <sepolicy>\n"
+    "        <kernel-sepolicy-version>30</kernel-sepolicy-version>\n"
+    "        <sepolicy-version>25.5</sepolicy-version>\n"
+    "    </sepolicy>\n"
+    "</compatibility-matrix>\n";
+
 class VintfObjectTestBase : public ::testing::Test {
    protected:
     MockFileSystem& fetcher() {
@@ -585,6 +606,28 @@
     ASSERT_STREQ(error.c_str(), "");
 }
 
+// Test that framework-only OTA fails when kernel is not compatible with incoming system.
+TEST_F(VintfObjectCompatibleTest, KernelInfoIncompatible) {
+    std::string error;
+    std::vector<std::string> packageInfo = {systemMatrixKernel318};
+
+    int result = checkCompatibility(packageInfo, &error);
+
+    ASSERT_EQ(result, INCOMPATIBLE) << "Should have failed.";
+    EXPECT_IN("Framework is incompatible with kernel version 3.18.31", error);
+}
+
+// Test that full OTA is successful when the OTA package provides a compatible kernel.
+TEST_F(VintfObjectCompatibleTest, UpdateKernel) {
+    std::string error;
+    std::vector<std::string> packageInfo = {vendorManifestKernel318, systemMatrixKernel318};
+
+    int result = checkCompatibility(packageInfo, &error);
+
+    ASSERT_EQ(result, COMPATIBLE) << "Fail message:" << error;
+    ASSERT_STREQ(error.c_str(), "");
+}
+
 // Test fixture that provides incompatible metadata from the mock device.
 class VintfObjectIncompatibleTest : public VintfObjectTestBase {
    protected:
diff --git a/xsd/compatibilityMatrix/api/current.txt b/xsd/compatibilityMatrix/api/current.txt
index 3db4d27..a504dbb 100644
--- a/xsd/compatibilityMatrix/api/current.txt
+++ b/xsd/compatibilityMatrix/api/current.txt
@@ -41,7 +41,9 @@
   public static class Config.Value {
     ctor public Config.Value();
     method public String getType();
+    method public String getValue();
     method public void setType(String);
+    method public void setValue(String);
   }
 
   public class Hal {
diff --git a/xsd/compatibilityMatrix/compatibility_matrix.xsd b/xsd/compatibilityMatrix/compatibility_matrix.xsd
index 7c2c8a0..b8c9fa5 100644
--- a/xsd/compatibilityMatrix/compatibility_matrix.xsd
+++ b/xsd/compatibilityMatrix/compatibility_matrix.xsd
@@ -21,14 +21,14 @@
     <xs:element name="compatibility-matrix">
         <xs:complexType>
             <xs:sequence>
-                <xs:element name="hal" type="hal" maxOccurs="unbounded"/>
-                <xs:element name="kernel" type="kernel" maxOccurs="unbounded"/>
-                <xs:element name="sepolicy" type="sepolicy"/>
-                <xs:element name="avb" type="avb"/>
-                <xs:element name="vndk" type="vndk"/>
-                <xs:element name="vendor-ndk" type="vendor-ndk"/>
-                <xs:element name="system-sdk" type="system-sdk"/>
-                <xs:element name="xmlfile" type="xmlfile" maxOccurs="unbounded"/>
+                <xs:element name="hal" type="hal" minOccurs="0" maxOccurs="unbounded"/>
+                <xs:element name="kernel" type="kernel" minOccurs="0" maxOccurs="unbounded"/>
+                <xs:element name="sepolicy" type="sepolicy" minOccurs="0"/>
+                <xs:element name="avb" type="avb" minOccurs="0"/>
+                <xs:element name="vndk" type="vndk" minOccurs="0"/>
+                <xs:element name="vendor-ndk" type="vendor-ndk" minOccurs="0"/>
+                <xs:element name="system-sdk" type="system-sdk" minOccurs="0"/>
+                <xs:element name="xmlfile" type="xmlfile" minOccurs="0" maxOccurs="unbounded"/>
             </xs:sequence>
             <xs:attribute name="version" type="xs:string" use="required"/>
             <xs:attribute name="type" type="xs:string" use="required"/>
@@ -38,9 +38,9 @@
     <xs:complexType name="hal">
         <xs:sequence>
             <xs:element name="name" type="xs:string"/>
-            <xs:element name="version" type="xs:string" maxOccurs="unbounded"/>
-            <xs:element name="interface" type="interface" maxOccurs="unbounded"/>
-            <xs:element name="fqname" type="xs:string" maxOccurs="unbounded"/>
+            <xs:element name="version" type="xs:string" minOccurs="0" maxOccurs="unbounded"/>
+            <xs:element name="interface" type="interface" minOccurs="0" maxOccurs="unbounded"/>
+            <xs:element name="fqname" type="xs:string" minOccurs="0" maxOccurs="unbounded"/>
         </xs:sequence>
         <xs:attribute name="format" type="xs:string"/>
         <xs:attribute name="optional" type="xs:string"/>
@@ -48,20 +48,20 @@
     <xs:complexType name="interface">
         <xs:sequence>
             <xs:element name="name" type="xs:string"/>
-            <xs:element name="instance" type="xs:string" maxOccurs="unbounded"/>
-            <xs:element name="regex-instance" type="xs:string" maxOccurs="unbounded"/>
+            <xs:element name="instance" type="xs:string" minOccurs="0" maxOccurs="unbounded"/>
+            <xs:element name="regex-instance" type="xs:string" minOccurs="0" maxOccurs="unbounded"/>
         </xs:sequence>
     </xs:complexType>
     <xs:complexType name="kernel">
         <xs:sequence>
-            <xs:element name="conditions">
+            <xs:element name="conditions" minOccurs="0">
                 <xs:complexType>
                     <xs:sequence>
-                        <xs:element name="config" type="config" maxOccurs="unbounded"/>
+                        <xs:element name="config" type="config" minOccurs="0" maxOccurs="unbounded"/>
                     </xs:sequence>
                 </xs:complexType>
             </xs:element>
-            <xs:element name="config" type="config" maxOccurs="unbounded"/>
+            <xs:element name="config" type="config" minOccurs="0" maxOccurs="unbounded"/>
         </xs:sequence>
         <xs:attribute name="version" type="xs:string"/>
     </xs:complexType>
@@ -70,7 +70,11 @@
             <xs:element name="key" type="xs:string"/>
             <xs:element name="value">
                 <xs:complexType>
-                    <xs:attribute name="type" type="xs:string"/>
+                    <xs:simpleContent>
+                        <xs:extension base="xs:string">
+                            <xs:attribute name="type" type="xs:string"/>
+                        </xs:extension>
+                    </xs:simpleContent>
                 </xs:complexType>
             </xs:element>
         </xs:sequence>
@@ -78,7 +82,7 @@
     <xs:complexType name="sepolicy">
         <xs:sequence>
             <xs:element name="kernel-sepolicy-version" type="xs:string"/>
-            <xs:element name="sepolicy-version" type="xs:string" maxOccurs="unbounded"/>
+            <xs:element name="sepolicy-version" type="xs:string" minOccurs="0" maxOccurs="unbounded"/>
         </xs:sequence>
     </xs:complexType>
     <xs:complexType name="avb">
@@ -89,18 +93,18 @@
     <xs:complexType name="vndk">
         <xs:sequence>
             <xs:element name="version" type="xs:string"/>
-            <xs:element name="library" type="xs:string" maxOccurs="unbounded"/>
+            <xs:element name="library" type="xs:string" minOccurs="0" maxOccurs="unbounded"/>
         </xs:sequence>
     </xs:complexType>
     <xs:complexType name="vendor-ndk">
         <xs:sequence>
             <xs:element name="version" type="xs:string"/>
-            <xs:element name="library" type="xs:string" maxOccurs="unbounded"/>
+            <xs:element name="library" type="xs:string" minOccurs="0" maxOccurs="unbounded"/>
         </xs:sequence>
     </xs:complexType>
     <xs:complexType name="system-sdk">
         <xs:sequence>
-            <xs:element name="version" type="xs:string" maxOccurs="unbounded"/>
+            <xs:element name="version" type="xs:string" minOccurs="0" maxOccurs="unbounded"/>
         </xs:sequence>
     </xs:complexType>
     <xs:complexType name="xmlfile">
diff --git a/xsd/halManifest/api/current.txt b/xsd/halManifest/api/current.txt
index 938324c..13acf6b 100644
--- a/xsd/halManifest/api/current.txt
+++ b/xsd/halManifest/api/current.txt
@@ -7,24 +7,49 @@
     method public java.util.List<java.lang.String> getFqname();
     method public String getName();
     method public String getOptional();
+    method public hal.manifest.Hal.Transport getTransport();
     method public java.util.List<java.lang.String> getVersion();
     method public java.util.List<hal.manifest.Interface> get_interface();
     method public void setFormat(String);
     method public void setName(String);
     method public void setOptional(String);
+    method public void setTransport(hal.manifest.Hal.Transport);
+  }
+
+  public static class Hal.Transport {
+    ctor public Hal.Transport();
+    method public String getArch();
+    method public String getValue();
+    method public void setArch(String);
+    method public void setValue(String);
   }
 
   public class Interface {
     ctor public Interface();
     method public java.util.List<java.lang.String> getInstance();
     method public String getName();
-    method public java.util.List<java.lang.String> getRegexinstance();
     method public void setName(String);
   }
 
+  public class Kernel {
+    ctor public Kernel();
+    method public java.util.List<hal.manifest.Kernel.Config> getConfig();
+    method public String getVersion();
+    method public void setVersion(String);
+  }
+
+  public static class Kernel.Config {
+    ctor public Kernel.Config();
+    method public String getKey();
+    method public String getValue();
+    method public void setKey(String);
+    method public void setValue(String);
+  }
+
   public class Manifest {
     ctor public Manifest();
     method public java.util.List<hal.manifest.Hal> getHal();
+    method public hal.manifest.Kernel getKernel();
     method public hal.manifest.Sepolicy getSepolicy();
     method public hal.manifest.Systemsdk getSystemsdk();
     method public String getTargetlevel();
@@ -32,6 +57,7 @@
     method public java.util.List<hal.manifest.Vendorndk> getVendorndk();
     method public String getVersion();
     method public java.util.List<hal.manifest.Vndk> getVndk();
+    method public void setKernel(hal.manifest.Kernel);
     method public void setSepolicy(hal.manifest.Sepolicy);
     method public void setSystemsdk(hal.manifest.Systemsdk);
     method public void setTargetlevel(String);
@@ -41,9 +67,8 @@
 
   public class Sepolicy {
     ctor public Sepolicy();
-    method public String getKernelsepolicyversion();
-    method public java.util.List<java.lang.String> getSepolicyversion();
-    method public void setKernelsepolicyversion(String);
+    method public String getVersion();
+    method public void setVersion(String);
   }
 
   public class Systemsdk {
diff --git a/xsd/halManifest/hal_manifest.xsd b/xsd/halManifest/hal_manifest.xsd
index 635d2c2..688abeb 100644
--- a/xsd/halManifest/hal_manifest.xsd
+++ b/xsd/halManifest/hal_manifest.xsd
@@ -21,23 +21,33 @@
     <xs:element name="manifest">
         <xs:complexType>
             <xs:sequence>
-                <xs:element name="hal" type="hal" maxOccurs="unbounded"/>
-                <xs:element name="sepolicy" type="sepolicy"/>
-                <xs:element name="vndk" type="vndk" maxOccurs="unbounded"/>
-                <xs:element name="vendor-ndk" type="vendor-ndk" maxOccurs="unbounded"/>
-                <xs:element name="system-sdk" type="system-sdk"/>
+                <xs:element name="hal" type="hal" minOccurs="0" maxOccurs="unbounded"/>
+                <xs:element name="sepolicy" type="sepolicy" minOccurs="0"/>
+                <xs:element name="kernel" type="kernel" minOccurs="0"/>
+                <xs:element name="vndk" type="vndk" minOccurs="0" maxOccurs="unbounded"/>
+                <xs:element name="vendor-ndk" type="vendor-ndk" minOccurs="0" maxOccurs="unbounded"/>
+                <xs:element name="system-sdk" type="system-sdk" minOccurs="0"/>
             </xs:sequence>
             <xs:attribute name="version" type="xs:string" use="required"/>
             <xs:attribute name="type" type="xs:string" use="required"/>
-            <xs:attribute name="target-level" type="xs:string" use="required"/>
+            <xs:attribute name="target-level" type="xs:string"/>
         </xs:complexType>
     </xs:element>
     <xs:complexType name="hal">
         <xs:sequence>
             <xs:element name="name" type="xs:string"/>
-            <xs:element name="version" type="xs:string" maxOccurs="unbounded"/>
-            <xs:element name="interface" type="interface" maxOccurs="unbounded"/>
-            <xs:element name="fqname" type="xs:string" maxOccurs="unbounded"/>
+            <xs:element name="transport">
+                <xs:complexType>
+                    <xs:simpleContent>
+                        <xs:extension base="xs:string">
+                            <xs:attribute name="arch" type="xs:string"/>
+                        </xs:extension>
+                    </xs:simpleContent>
+                </xs:complexType>
+            </xs:element>
+            <xs:element name="version" type="xs:string" minOccurs="0" maxOccurs="unbounded"/>
+            <xs:element name="interface" type="interface" minOccurs="0" maxOccurs="unbounded"/>
+            <xs:element name="fqname" type="xs:string" minOccurs="0" maxOccurs="unbounded"/>
         </xs:sequence>
         <xs:attribute name="format" type="xs:string"/>
         <xs:attribute name="optional" type="xs:string"/>
@@ -45,31 +55,42 @@
     <xs:complexType name="interface">
         <xs:sequence>
             <xs:element name="name" type="xs:string"/>
-            <xs:element name="instance" type="xs:string" maxOccurs="unbounded"/>
-            <xs:element name="regex-instance" type="xs:string" maxOccurs="unbounded"/>
+            <xs:element name="instance" type="xs:string" minOccurs="0" maxOccurs="unbounded"/>
         </xs:sequence>
     </xs:complexType>
     <xs:complexType name="sepolicy">
         <xs:sequence>
-            <xs:element name="kernel-sepolicy-version" type="xs:string"/>
-            <xs:element name="sepolicy-version" type="xs:string" maxOccurs="unbounded"/>
+            <xs:element name="version" type="xs:string"/>
         </xs:sequence>
     </xs:complexType>
     <xs:complexType name="vndk">
         <xs:sequence>
             <xs:element name="version" type="xs:string"/>
-            <xs:element name="library" type="xs:string" maxOccurs="unbounded"/>
+            <xs:element name="library" type="xs:string" minOccurs="0" maxOccurs="unbounded"/>
         </xs:sequence>
     </xs:complexType>
     <xs:complexType name="vendor-ndk">
         <xs:sequence>
             <xs:element name="version" type="xs:string"/>
-            <xs:element name="library" type="xs:string" maxOccurs="unbounded"/>
+            <xs:element name="library" type="xs:string" minOccurs="0" maxOccurs="unbounded"/>
         </xs:sequence>
     </xs:complexType>
     <xs:complexType name="system-sdk">
         <xs:sequence>
-            <xs:element name="version" type="xs:string" maxOccurs="unbounded"/>
+            <xs:element name="version" type="xs:string" minOccurs="0" maxOccurs="unbounded"/>
         </xs:sequence>
     </xs:complexType>
+    <xs:complexType name="kernel">
+        <xs:sequence>
+            <xs:element name="config" minOccurs="0" maxOccurs="unbounded">
+                <xs:complexType>
+                    <xs:sequence>
+                        <xs:element name="key" type="xs:string"/>
+                        <xs:element name="value" type="xs:string"/>
+                    </xs:sequence>
+                </xs:complexType>
+            </xs:element>
+        </xs:sequence>
+        <xs:attribute name="version" type="xs:string"/>
+    </xs:complexType>
 </xs:schema>