Merge manifest kernels.

Merge manually written device manifest with kernel
FCM version with auto-generated device manifest from
kernel version / configs.

Test: libvintf_test
Bug: 139309488
Change-Id: If7ae8232461eec9fcc83b03194353db953ce087d
diff --git a/KernelInfo.cpp b/KernelInfo.cpp
index ec8abac..a2c594f 100644
--- a/KernelInfo.cpp
+++ b/KernelInfo.cpp
@@ -16,10 +16,13 @@
 #include "KernelInfo.h"
 
 #include "parse_string.h"
+#include "utils.h"
 
 namespace android {
 namespace vintf {
 
+using details::mergeField;
+
 const KernelVersion& KernelInfo::version() const {
     return mVersion;
 }
@@ -111,5 +114,32 @@
     return mVersion == other.mVersion && mConfigs == other.mConfigs;
 }
 
+bool KernelInfo::merge(KernelInfo* other, std::string* error) {
+    if (!mergeField(&mVersion, &other->mVersion)) {
+        if (error) {
+            *error = "Conflicting kernel version: " + to_string(version()) + " vs. " +
+                     to_string(other->version());
+        }
+        return false;
+    }
+
+    // Do not allow merging configs. One of them must be empty.
+    if (!mergeField(&mConfigs, &other->mConfigs)) {
+        if (error) {
+            *error = "Found <kernel><config> items in two manifests.";
+        }
+        return false;
+    }
+
+    if (!mergeField(&mLevel, &other->mLevel, Level::UNSPECIFIED)) {
+        if (error) {
+            *error = "Conflicting kernel level: " + to_string(level()) + " vs. " +
+                     to_string(other->level());
+        }
+        return false;
+    }
+    return true;
+}
+
 }  // namespace vintf
 }  // namespace android