Implement FCM Version in matrices / manifests.
"level" is an attribute on compatibility matrices / manifests
to specify the FCM Version they declare / implement. Value can
be "legacy" or a positive number, or empty (for old files).
Test: libvintf_test
Test: Built manifests / matrices has not changed (because
value is "unspecified").
Bug: 69854976 device manfiest must specify FCM Version
Bug: 69636193 all matrices should be installed to system image
Bug: 64720381 deprecation schedule
Change-Id: I15d34343fae4ad79d86bd50e9de8c4f6ac09fdfd
Merged-In: I15d34343fae4ad79d86bd50e9de8c4f6ac09fdfd
diff --git a/CompatibilityMatrix.cpp b/CompatibilityMatrix.cpp
index 73d0384..f788569 100644
--- a/CompatibilityMatrix.cpp
+++ b/CompatibilityMatrix.cpp
@@ -38,6 +38,10 @@
return mType;
}
+Level CompatibilityMatrix::level() const {
+ return mLevel;
+}
+
Version CompatibilityMatrix::getMinimumMetaVersion() const {
// TODO(b/62801658): this needs to depend on whether there are 1.1 requirements
// (e.g. required <xmlfile> entry)
@@ -68,7 +72,8 @@
}
bool operator==(const CompatibilityMatrix &lft, const CompatibilityMatrix &rgt) {
- return lft.mType == rgt.mType && lft.mHals == rgt.mHals && lft.mXmlFiles == rgt.mXmlFiles &&
+ return lft.mType == rgt.mType && lft.mLevel == rgt.mLevel && lft.mHals == rgt.mHals &&
+ lft.mXmlFiles == rgt.mXmlFiles &&
(lft.mType != SchemaType::DEVICE || (lft.device.mVndk == rgt.device.mVndk)) &&
(lft.mType != SchemaType::FRAMEWORK ||
(lft.framework.mKernels == rgt.framework.mKernels &&
diff --git a/HalManifest.cpp b/HalManifest.cpp
index c633a7a..9683729 100644
--- a/HalManifest.cpp
+++ b/HalManifest.cpp
@@ -319,6 +319,10 @@
return mType;
}
+Level HalManifest::level() const {
+ return mLevel;
+}
+
Version HalManifest::getMetaVersion() const {
return mMetaVersion;
}
@@ -352,7 +356,8 @@
}
bool operator==(const HalManifest &lft, const HalManifest &rgt) {
- return lft.mType == rgt.mType && lft.mHals == rgt.mHals && lft.mXmlFiles == rgt.mXmlFiles &&
+ 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.mType != SchemaType::FRAMEWORK || (lft.framework.mVndks == rgt.framework.mVndks));
diff --git a/include/vintf/CompatibilityMatrix.h b/include/vintf/CompatibilityMatrix.h
index bc3fbf4..c9a8a9f 100644
--- a/include/vintf/CompatibilityMatrix.h
+++ b/include/vintf/CompatibilityMatrix.h
@@ -23,6 +23,7 @@
#include <utils/Errors.h>
#include "HalGroup.h"
+#include "Level.h"
#include "MapValueIterator.h"
#include "MatrixHal.h"
#include "MatrixKernel.h"
@@ -40,6 +41,7 @@
CompatibilityMatrix() : mType(SchemaType::FRAMEWORK) {};
SchemaType type() const;
+ Level level() const;
Version getMinimumMetaVersion() const;
// If the corresponding <xmlfile> with the given version exists, for the first match,
@@ -68,6 +70,7 @@
friend bool operator==(const CompatibilityMatrix &, const CompatibilityMatrix &);
SchemaType mType;
+ Level mLevel = Level::UNSPECIFIED;
// entries only for framework compatibility matrix.
struct {
diff --git a/include/vintf/HalManifest.h b/include/vintf/HalManifest.h
index b553371..46657de 100644
--- a/include/vintf/HalManifest.h
+++ b/include/vintf/HalManifest.h
@@ -24,6 +24,7 @@
#include <vector>
#include "HalGroup.h"
+#include "Level.h"
#include "ManifestHal.h"
#include "MapValueIterator.h"
#include "SchemaType.h"
@@ -93,6 +94,9 @@
// Type of the manifest. FRAMEWORK or DEVICE.
SchemaType type() const;
+ // FCM version that it implements.
+ Level level() const;
+
// device.mSepolicyVersion. Assume type == device.
// Abort if type != device.
const Version &sepolicyVersion() const;
@@ -132,6 +136,7 @@
bool includeOptional = true) const;
SchemaType mType;
+ Level mLevel = Level::UNSPECIFIED;
// version attribute. Default is 1.0 for manifests created programatically.
Version mMetaVersion{1, 0};
diff --git a/include/vintf/Level.h b/include/vintf/Level.h
new file mode 100644
index 0000000..49dad0b
--- /dev/null
+++ b/include/vintf/Level.h
@@ -0,0 +1,44 @@
+/*
+ * 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_LEVEL_H
+#define ANDROID_VINTF_LEVEL_H
+
+#include <stdint.h>
+
+namespace android {
+namespace vintf {
+
+// Manifest and Compatibility Matrix Level, a.k.a FCM Version, is a number assigned to each
+// manifest / matrix.
+// - For manifest, the FCM Version that it implements
+// - For matrix, the single FCM Version that this matrix file details.
+// This is not a strong-typed enum because Level can be any integer value. Listed are some
+// special values.
+enum Level : size_t {
+ // Non-Treble devices.
+ LEGACY = 0,
+ // Actual values starts from 1. Following are some historic values for convenience.
+ O = 1,
+ O_MR1 = 2,
+ // For older manifests and compatibility matrices, "level" is not specified.
+ UNSPECIFIED = SIZE_MAX,
+};
+
+} // namespace vintf
+} // namespace android
+
+#endif // ANDROID_VINTF_LEVEL_H
diff --git a/include/vintf/parse_string.h b/include/vintf/parse_string.h
index 77d1830..00844d7 100644
--- a/include/vintf/parse_string.h
+++ b/include/vintf/parse_string.h
@@ -35,6 +35,7 @@
std::ostream &operator<<(std::ostream &os, Tristate tr);
std::ostream &operator<<(std::ostream &os, SchemaType ksv);
std::ostream& operator<<(std::ostream& os, XmlSchemaFormat f);
+std::ostream& operator<<(std::ostream& os, Level l);
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);
@@ -60,6 +61,7 @@
bool parse(const std::string &s, Tristate *tr);
bool parse(const std::string &s, SchemaType *ver);
bool parse(const std::string& s, XmlSchemaFormat* ver);
+bool parse(const std::string& s, Level* l);
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 a6bb418..7e23f5f 100644
--- a/parse_string.cpp
+++ b/parse_string.cpp
@@ -113,6 +113,33 @@
}
}
+bool parse(const std::string& s, Level* l) {
+ if (s.empty()) {
+ *l = Level::UNSPECIFIED;
+ return true;
+ }
+ if (s == "legacy") {
+ *l = Level::LEGACY;
+ return true;
+ }
+ size_t value;
+ if (!ParseUint(s, &value)) {
+ return false;
+ }
+ *l = static_cast<Level>(value);
+ return true;
+}
+
+std::ostream& operator<<(std::ostream& os, Level l) {
+ if (l == Level::UNSPECIFIED) {
+ return os;
+ }
+ if (l == Level::LEGACY) {
+ return os << "legacy";
+ }
+ return os << static_cast<size_t>(l);
+}
+
// Notice that strtoull is used even though KernelConfigIntValue is signed int64_t,
// because strtoull can accept negative values as well.
// Notice that according to man strtoul, strtoull can actually accept
diff --git a/parse_xml.cpp b/parse_xml.cpp
index 1a0626a..350d10b 100644
--- a/parse_xml.cpp
+++ b/parse_xml.cpp
@@ -748,7 +748,9 @@
void mutateNode(const HalManifest &m, NodeType *root, DocType *d) const override {
appendAttr(root, "version", m.getMetaVersion());
appendAttr(root, "type", m.mType);
-
+ if (m.mLevel != Level::UNSPECIFIED) {
+ this->appendAttr(root, "target-level", m.mLevel);
+ }
appendChildren(root, manifestHalConverter, m.getHals(), d);
if (m.mType == SchemaType::DEVICE) {
appendChild(root, halManifestSepolicyConverter(m.device.mSepolicyVersion, d));
@@ -762,6 +764,7 @@
std::vector<ManifestHal> hals;
if (!parseAttr(root, "version", &object->mMetaVersion) ||
!parseAttr(root, "type", &object->mType) ||
+ !parseOptionalAttr(root, "target-level", Level::UNSPECIFIED, &object->mLevel) ||
!parseChildren(root, manifestHalConverter, &hals)) {
return false;
}
@@ -858,6 +861,9 @@
void mutateNode(const CompatibilityMatrix &m, NodeType *root, DocType *d) const override {
appendAttr(root, "version", m.getMinimumMetaVersion());
appendAttr(root, "type", m.mType);
+ if (m.mLevel != Level::UNSPECIFIED) {
+ this->appendAttr(root, "level", m.mLevel);
+ }
appendChildren(root, matrixHalConverter, iterateValues(m.mHals), d);
if (m.mType == SchemaType::FRAMEWORK) {
appendChildren(root, matrixKernelConverter, m.framework.mKernels, d);
@@ -872,8 +878,8 @@
bool buildObject(CompatibilityMatrix *object, NodeType *root) const override {
Version version;
std::vector<MatrixHal> hals;
- if (!parseAttr(root, "version", &version) ||
- !parseAttr(root, "type", &object->mType) ||
+ if (!parseAttr(root, "version", &version) || !parseAttr(root, "type", &object->mType) ||
+ !parseOptionalAttr(root, "level", Level::UNSPECIFIED, &object->mLevel) ||
!parseChildren(root, matrixHalConverter, &hals)) {
return false;
}
diff --git a/test/main.cpp b/test/main.cpp
index 8ec02a8..b8a25a2 100644
--- a/test/main.cpp
+++ b/test/main.cpp
@@ -2047,6 +2047,43 @@
INSTANTIATE_TEST_CASE_P(KernelConfigParser, KernelConfigParserInvalidTest, ::testing::Bool());
+TEST_F(LibVintfTest, MatrixLevel) {
+ CompatibilityMatrix cm;
+ std::string xml;
+
+ xml = "<compatibility-matrix version=\"1.0\" type=\"framework\"/>";
+ EXPECT_TRUE(gCompatibilityMatrixConverter(&cm, xml))
+ << gCompatibilityMatrixConverter.lastError();
+ EXPECT_EQ(Level::UNSPECIFIED, cm.level());
+
+ xml = "<compatibility-matrix version=\"1.0\" type=\"framework\" level=\"legacy\"/>";
+ EXPECT_TRUE(gCompatibilityMatrixConverter(&cm, xml))
+ << gCompatibilityMatrixConverter.lastError();
+ EXPECT_EQ(Level::LEGACY, cm.level());
+
+ xml = "<compatibility-matrix version=\"1.0\" type=\"framework\" level=\"1\"/>";
+ EXPECT_TRUE(gCompatibilityMatrixConverter(&cm, xml))
+ << gCompatibilityMatrixConverter.lastError();
+ EXPECT_EQ(1u, cm.level());
+}
+
+TEST_F(LibVintfTest, ManifestLevel) {
+ HalManifest manifest;
+ std::string xml;
+
+ xml = "<manifest version=\"1.0\" type=\"device\"/>";
+ EXPECT_TRUE(gHalManifestConverter(&manifest, xml)) << gHalManifestConverter.lastError();
+ EXPECT_EQ(Level::UNSPECIFIED, manifest.level());
+
+ xml = "<manifest version=\"1.0\" type=\"device\" target-level=\"legacy\"/>";
+ EXPECT_TRUE(gHalManifestConverter(&manifest, xml)) << gHalManifestConverter.lastError();
+ EXPECT_EQ(Level::LEGACY, manifest.level());
+
+ xml = "<manifest version=\"1.0\" type=\"device\" target-level=\"1\"/>";
+ EXPECT_TRUE(gHalManifestConverter(&manifest, xml)) << gHalManifestConverter.lastError();
+ EXPECT_EQ(1u, manifest.level());
+}
+
} // namespace vintf
} // namespace android