Add manifest/compatibility-matrix.type attribute

to distinguish device and framework HAL manifest, and
device and framework compatibility matrix.

Add .device / .framework entries to HalManifest and
CompatibilityMatrix class for device-only / fwk-only
entries. Access to these fields should be guarded with
a check to mType.

Test: libvintf_test
Test: boots
Change-Id: Id9c93c1e6bb585234a9ae6d9296f5a10582ef58f
diff --git a/CompatibilityMatrix.cpp b/CompatibilityMatrix.cpp
index aba4efc..f27a019 100644
--- a/CompatibilityMatrix.cpp
+++ b/CompatibilityMatrix.cpp
@@ -26,13 +26,16 @@
 }
 
 bool CompatibilityMatrix::add(MatrixKernel &&kernel) {
-    mKernels.push_back(std::move(kernel));
+    if (mType != SchemaType::FRAMEWORK) {
+        return false;
+    }
+    framework.mKernels.push_back(std::move(kernel));
     return true;
 }
 
 void CompatibilityMatrix::clear() {
     mHals.clear();
-    mKernels.clear();
+    framework.mKernels.clear();
 }
 
 ConstMapValueIterable<std::string, MatrixHal> CompatibilityMatrix::getHals() const {
@@ -40,7 +43,10 @@
 }
 
 const MatrixKernel *CompatibilityMatrix::findKernel(const KernelVersion &v) const {
-    for (const MatrixKernel &matrixKernel : mKernels) {
+    if (mType != SchemaType::FRAMEWORK) {
+        return nullptr;
+    }
+    for (const MatrixKernel &matrixKernel : framework.mKernels) {
         if (matrixKernel.minLts().version == v.version &&
             matrixKernel.minLts().majorRev == v.majorRev) {
             return matrixKernel.minLts().minorRev <= v.minorRev ? &matrixKernel : nullptr;
diff --git a/RuntimeInfo.cpp b/RuntimeInfo.cpp
index 6b09a7c..c14ea95 100644
--- a/RuntimeInfo.cpp
+++ b/RuntimeInfo.cpp
@@ -242,10 +242,17 @@
 
 bool RuntimeInfo::checkCompatibility(const CompatibilityMatrix &mat,
             std::string *error) const {
-    if (kernelSepolicyVersion() != mat.mSepolicy.kernelSepolicyVersion()) {
+    if (mat.mType != SchemaType::FRAMEWORK) {
+        if (error != nullptr) {
+            *error = "Should not check runtime info against " + to_string(mat.mType)
+                    + " compatibility matrix.";
+        }
+        return false;
+    }
+    if (kernelSepolicyVersion() != mat.framework.mSepolicy.kernelSepolicyVersion()) {
         if (error != nullptr) {
             *error = "kernelSepolicyVersion = " + to_string(kernelSepolicyVersion())
-                     + " but required " + to_string(mat.mSepolicy.kernelSepolicyVersion());
+                     + " but required " + to_string(mat.framework.mSepolicy.kernelSepolicyVersion());
         }
         return false;
     }
diff --git a/include/vintf/CompatibilityMatrix.h b/include/vintf/CompatibilityMatrix.h
index 515c2b8..007471a 100644
--- a/include/vintf/CompatibilityMatrix.h
+++ b/include/vintf/CompatibilityMatrix.h
@@ -24,12 +24,17 @@
 #include "MatrixKernel.h"
 #include "MapValueIterator.h"
 #include "Sepolicy.h"
+#include "SchemaType.h"
 
 namespace android {
 namespace vintf {
 
 // Compatibility matrix defines what hardware does the framework requires.
 struct CompatibilityMatrix {
+
+    // Create a framework compatibility matrix.
+    CompatibilityMatrix() : mType(SchemaType::FRAMEWORK) {};
+
     constexpr static Version kVersion{1, 0};
 
 private:
@@ -49,12 +54,16 @@
     friend struct CompatibilityMatrixConverter;
     friend struct LibVintfTest;
 
+    SchemaType mType;
+
     // sorted map from component name to the entry.
     std::map<std::string, MatrixHal> mHals;
 
-    std::vector<MatrixKernel> mKernels;
-
-    Sepolicy mSepolicy;
+    // entries only for framework compatibility matrix.
+    struct {
+        std::vector<MatrixKernel> mKernels;
+        Sepolicy mSepolicy;
+    } framework;
 };
 
 } // namespace vintf
diff --git a/include/vintf/HalManifest.h b/include/vintf/HalManifest.h
index 91a2e08..a260d00 100644
--- a/include/vintf/HalManifest.h
+++ b/include/vintf/HalManifest.h
@@ -25,6 +25,7 @@
 
 #include "ManifestHal.h"
 #include "MapValueIterator.h"
+#include "SchemaType.h"
 #include "Version.h"
 
 namespace android {
@@ -40,7 +41,8 @@
     // manifest.version
     constexpr static Version kVersion{1, 0};
 
-    HalManifest() {}
+    // Construct a device HAL manifest.
+    HalManifest() : mType(SchemaType::DEVICE) {}
 
     // Given a component name (e.g. "android.hardware.camera"),
     // return getHal(name)->transport if the component exist and v exactly matches
@@ -91,6 +93,7 @@
 private:
     friend struct HalManifestConverter;
     friend class VintfObject;
+    friend class AssembleVintf;
     friend struct LibVintfTest;
     friend std::string dump(const HalManifest &vm);
 
@@ -103,9 +106,15 @@
 
     status_t fetchAllInformation(const std::string &path);
 
+    SchemaType mType;
+
     // sorted map from component name to the component.
     // The component name looks like: android.hardware.foo
     std::map<std::string, ManifestHal> mHals;
+
+    // entries for device hal manifest only
+    struct {
+    } device;
 };
 
 
diff --git a/include/vintf/SchemaType.h b/include/vintf/SchemaType.h
new file mode 100644
index 0000000..4254957
--- /dev/null
+++ b/include/vintf/SchemaType.h
@@ -0,0 +1,42 @@
+/*
+ * 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_MANIFEST_TYPE_H
+#define ANDROID_VINTF_MANIFEST_TYPE_H
+
+#include <stdint.h>
+#include <string>
+#include <array>
+
+namespace android {
+namespace vintf {
+
+enum class SchemaType : size_t {
+    DEVICE = 0,
+    FRAMEWORK,
+};
+
+static const std::array<std::string, 2> gSchemaTypeStrings = {
+    {
+        "device",
+        "framework",
+    }
+};
+
+} // namespace vintf
+} // namespace android
+
+#endif // ANDROID_VINTF_MANIFEST_TYPE_H
diff --git a/include/vintf/parse_string.h b/include/vintf/parse_string.h
index 8c81de4..15775e4 100644
--- a/include/vintf/parse_string.h
+++ b/include/vintf/parse_string.h
@@ -33,7 +33,8 @@
 std::ostream &operator<<(std::ostream &os, Arch ar);
 std::ostream &operator<<(std::ostream &os, KernelConfigType il);
 std::ostream &operator<<(std::ostream &os, Tristate tr);
-std::ostream &operator<<(std::ostream &os, KernelSepolicyVersion ksv);
+std::ostream &operator<<(std::ostream &os, SchemaType ksv);
+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);
 std::ostream &operator<<(std::ostream &os, const KernelVersion &ver);
@@ -56,6 +57,7 @@
 bool parse(const std::string &s, KernelConfigType *il);
 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, 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 cec3adf..20daad9 100644
--- a/parse_string.cpp
+++ b/parse_string.cpp
@@ -96,6 +96,7 @@
 DEFINE_PARSE_STREAMIN_FOR_ENUM(Arch);
 DEFINE_PARSE_STREAMIN_FOR_ENUM(KernelConfigType);
 DEFINE_PARSE_STREAMIN_FOR_ENUM(Tristate);
+DEFINE_PARSE_STREAMIN_FOR_ENUM(SchemaType);
 
 std::ostream &operator<<(std::ostream &os, const KernelConfigTypedValue &kctv) {
     switch (kctv.mType) {
diff --git a/parse_xml.cpp b/parse_xml.cpp
index f52f849..7500797 100644
--- a/parse_xml.cpp
+++ b/parse_xml.cpp
@@ -543,11 +543,19 @@
     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);
     }
     bool buildObject(HalManifest *object, NodeType *root) const override {
+        Version version;
         std::vector<ManifestHal> hals;
-        if (!parseChildren(root, manifestHalConverter, &hals)) {
+        if (!parseAttr(root, "version", &version) ||
+            !parseAttr(root, "type", &object->mType) ||
+            !parseChildren(root, manifestHalConverter, &hals)) {
+            return false;
+        }
+        if (version != HalManifest::kVersion) {
+            this->mLastError = "Unrecognized manifest.version";
             return false;
         }
         for (auto &&hal : hals) {
@@ -566,15 +574,31 @@
     std::string elementName() const override { return "compatibility-matrix"; }
     void mutateNode(const CompatibilityMatrix &m, NodeType *root, DocType *d) const override {
         appendAttr(root, "version", CompatibilityMatrix::kVersion);
+        appendAttr(root, "type", m.mType);
         appendChildren(root, matrixHalConverter, iterateValues(m.mHals), d);
-        appendChildren(root, matrixKernelConverter, m.mKernels, d);
-        appendChild(root, sepolicyConverter(m.mSepolicy, d));
+        if (m.mType == SchemaType::FRAMEWORK) {
+            appendChildren(root, matrixKernelConverter, m.framework.mKernels, d);
+            appendChild(root, sepolicyConverter(m.framework.mSepolicy, d));
+        }
     }
     bool buildObject(CompatibilityMatrix *object, NodeType *root) const override {
+        Version version;
         std::vector<MatrixHal> hals;
-        if (!parseChildren(root, matrixHalConverter, &hals) ||
-            !parseChildren(root, matrixKernelConverter, &object->mKernels) ||
-            !parseChild(root, sepolicyConverter, &object->mSepolicy)) {
+        if (!parseAttr(root, "version", &version) ||
+            !parseAttr(root, "type", &object->mType) ||
+            !parseChildren(root, matrixHalConverter, &hals)) {
+            return false;
+        }
+
+        if (object->mType == SchemaType::FRAMEWORK) {
+            if (!parseChildren(root, matrixKernelConverter, &object->framework.mKernels) ||
+                !parseChild(root, sepolicyConverter, &object->framework.mSepolicy)) {
+                return false;
+            }
+        }
+
+        if (version != CompatibilityMatrix::kVersion) {
+            this->mLastError = "Unrecognized compatibility-matrix.version";
             return false;
         }
         for (auto &&hal : hals) {
diff --git a/test/main.cpp b/test/main.cpp
index 61b6bd9..582ac19 100644
--- a/test/main.cpp
+++ b/test/main.cpp
@@ -52,7 +52,7 @@
         return vm.add(std::move(hal));
     }
     void set(CompatibilityMatrix &cm, Sepolicy &&sepolicy) {
-        cm.mSepolicy = sepolicy;
+        cm.framework.mSepolicy = sepolicy;
     }
     const ManifestHal *getHal(HalManifest &vm, const std::string &name) {
         return vm.getHal(name);
@@ -61,13 +61,14 @@
         return vm.getHals();
     }
     bool isEqual(const CompatibilityMatrix &cm1, const CompatibilityMatrix &cm2) {
-        return cm1.mHals == cm2.mHals && cm1.mKernels == cm2.mKernels;
+        return cm1.mHals == cm2.mHals && cm1.framework.mKernels == cm2.framework.mKernels;
     }
     bool isValid(const ManifestHal &mh) {
         return mh.isValid();
     }
     HalManifest testHalManifest() {
         HalManifest vm;
+        vm.mType = SchemaType::DEVICE;
         vm.add(ManifestHal{
             .format = HalFormat::HIDL,
             .name = "android.hardware.camera",
@@ -130,7 +131,7 @@
     HalManifest vm = testHalManifest();
     std::string xml = gHalManifestConverter(vm);
     EXPECT_EQ(xml,
-        "<manifest version=\"1.0\">\n"
+        "<manifest version=\"1.0\" type=\"device\">\n"
         "    <hal format=\"hidl\">\n"
         "        <name>android.hardware.camera</name>\n"
         "        <transport>hwbinder</transport>\n"
@@ -160,9 +161,9 @@
 TEST_F(LibVintfTest, HalManifestOptional) {
     HalManifest vm;
     EXPECT_TRUE(gHalManifestConverter(&vm,
-            "<manifest version=\"1.0\"></manifest>"));
+            "<manifest version=\"1.0\" type=\"device\"></manifest>"));
     EXPECT_TRUE(gHalManifestConverter(&vm,
-            "<manifest version=\"1.0\">"
+            "<manifest version=\"1.0\" type=\"device\">"
             "    <hal>"
             "        <name>android.hidl.manager</name>"
             "        <transport>hwbinder</transport>"
@@ -170,7 +171,7 @@
             "    </hal>"
             "</manifest>"));
     EXPECT_FALSE(gHalManifestConverter(&vm,
-            "<manifest version=\"1.0\">"
+            "<manifest version=\"1.0\" type=\"device\">"
             "    <hal>"
             "        <name>android.hidl.manager</name>"
             "        <version>1.0</version>"
@@ -325,7 +326,7 @@
     set(cm, Sepolicy(30, {1, 3}));
     std::string xml = gCompatibilityMatrixConverter(cm);
     EXPECT_EQ(xml,
-            "<compatibility-matrix version=\"1.0\">\n"
+            "<compatibility-matrix version=\"1.0\" type=\"framework\">\n"
             "    <hal format=\"native\" optional=\"false\">\n"
             "        <name>android.hardware.camera</name>\n"
             "        <version>1.2-3</version>\n"