Support <system-sdk> in fwk manifest and dev matrix.
<system-sdk> is a tag in framework manifest and
device matrix. It states a list of System SDK levels
that the framework supports for vendor apps / vendor
apps requires.
Format:
<system-sdk>
<version>14</version>
<version>15</version>
</system-sdk>
Versions must not be duplicated.
It is compatible when the set specified in framework
manifest is a superset of the set specified in the
device compatibility matrix.
Test: libvintf_test
Test: vintf_object_tests
Bug: 69088799
Change-Id: I802f055ea60666995202438a770d1e440517ec5c
diff --git a/Android.bp b/Android.bp
index fea4d38..a2f647e 100644
--- a/Android.bp
+++ b/Android.bp
@@ -24,10 +24,30 @@
],
}
+cc_defaults {
+ name: "libvintf-common-srcs",
+ srcs: [
+ "parse_string.cpp",
+ "parse_xml.cpp",
+ "CompatibilityMatrix.cpp",
+ "HalManifest.cpp",
+ "HalInterface.cpp",
+ "KernelConfigTypedValue.cpp",
+ "RuntimeInfo.cpp",
+ "ManifestHal.cpp",
+ "MatrixHal.cpp",
+ "MatrixKernel.cpp",
+ "SystemSdk.cpp",
+ "TransportArch.cpp",
+ "VintfObject.cpp",
+ "XmlFile.cpp",
+ ]
+}
+
cc_library {
name: "libvintf",
host_supported: true,
- defaults: ["libvintf-defaults"],
+ defaults: ["libvintf-defaults", "libvintf-common-srcs"],
shared_libs: [
"libbase",
"liblog",
@@ -38,20 +58,7 @@
local_include_dirs: ["include/vintf"],
srcs: [
- "parse_string.cpp",
- "parse_xml.cpp",
- "CompatibilityMatrix.cpp",
- "HalManifest.cpp",
- "HalInterface.cpp",
"KernelConfigParser.cpp",
- "KernelConfigTypedValue.cpp",
- "RuntimeInfo.cpp",
- "ManifestHal.cpp",
- "MatrixHal.cpp",
- "MatrixKernel.cpp",
- "TransportArch.cpp",
- "VintfObject.cpp",
- "XmlFile.cpp",
"utils.cpp",
],
@@ -136,7 +143,7 @@
cc_library_static {
name: "libvintftest",
- defaults: ["libvintf-defaults"],
+ defaults: ["libvintf-defaults", "libvintf-common-srcs"],
host_supported: true,
shared_libs: [
"libbase",
@@ -148,19 +155,6 @@
local_include_dirs: ["include/vintf", "test", "."],
srcs: [
- "parse_string.cpp",
- "parse_xml.cpp",
- "CompatibilityMatrix.cpp",
- "HalManifest.cpp",
- "HalInterface.cpp",
- "KernelConfigTypedValue.cpp",
- "RuntimeInfo.cpp",
- "ManifestHal.cpp",
- "MatrixHal.cpp",
- "MatrixKernel.cpp",
- "TransportArch.cpp",
- "VintfObject.cpp",
- "XmlFile.cpp",
"test/RuntimeInfo-fake.cpp",
"test/utils-fake.cpp",
],
diff --git a/AssembleVintf.cpp b/AssembleVintf.cpp
index e19096e..f7f1fb4 100644
--- a/AssembleVintf.cpp
+++ b/AssembleVintf.cpp
@@ -76,6 +76,18 @@
return envValue != nullptr ? std::string(envValue) : std::string();
}
+ // Get environment variable and split with space.
+ std::vector<std::string> getEnvList(const std::string& key) const {
+ std::vector<std::string> ret;
+ for (auto&& v : base::Split(getEnv(key), " ")) {
+ v = base::Trim(v);
+ if (!v.empty()) {
+ ret.push_back(v);
+ }
+ }
+ return ret;
+ }
+
template <typename T>
bool getFlag(const std::string& key, T* value) const {
std::string envValue = getEnv(key);
@@ -290,11 +302,12 @@
}
if (halManifest->mType == SchemaType::FRAMEWORK) {
- for (auto&& v : base::Split(getEnv("PROVIDED_VNDK_VERSIONS"), " ")) {
- v = base::Trim(v);
- if (!v.empty()) {
- halManifest->framework.mVendorNdks.emplace_back(std::move(v));
- }
+ for (auto&& v : getEnvList("PROVIDED_VNDK_VERSIONS")) {
+ halManifest->framework.mVendorNdks.emplace_back(std::move(v));
+ }
+
+ for (auto&& v : getEnvList("PRODUCT_SYSTEMSDK_VERSIONS")) {
+ halManifest->framework.mSystemSdk.mVersions.emplace(std::move(v));
}
}
@@ -416,6 +429,10 @@
}
valueInMatrix = VendorNdk{std::move(vndkVersion)};
}
+
+ for (auto&& v : getEnvList("BOARD_SYSTEMSDK_VERSIONS")) {
+ matrix->device.mSystemSdk.mVersions.emplace(std::move(v));
+ }
}
if (matrices->front().object.mType == SchemaType::FRAMEWORK) {
diff --git a/CompatibilityMatrix.cpp b/CompatibilityMatrix.cpp
index 8331f78..d3c4ebf 100644
--- a/CompatibilityMatrix.cpp
+++ b/CompatibilityMatrix.cpp
@@ -168,7 +168,8 @@
#pragma clang diagnostic ignored "-Wdeprecated-declarations"
lft.device.mVndk == rgt.device.mVndk &&
#pragma clang diagnostic pop
- lft.device.mVendorNdk == rgt.device.mVendorNdk)) &&
+ lft.device.mVendorNdk == rgt.device.mVendorNdk &&
+ lft.device.mSystemSdk == rgt.device.mSystemSdk)) &&
(lft.mType != SchemaType::FRAMEWORK ||
(lft.framework.mKernels == rgt.framework.mKernels &&
lft.framework.mSepolicy == rgt.framework.mSepolicy &&
diff --git a/HalManifest.cpp b/HalManifest.cpp
index 22ff292..20ed7eb 100644
--- a/HalManifest.cpp
+++ b/HalManifest.cpp
@@ -24,6 +24,8 @@
#include <mutex>
#include <set>
+#include <android-base/strings.h>
+
#include "parse_string.h"
#include "parse_xml.h"
#include "utils.h"
@@ -299,6 +301,22 @@
return false;
}
+static bool checkSystemSdkCompatibility(const SystemSdk& matSystemSdk,
+ const SystemSdk& manifestSystemSdk, std::string* error) {
+ SystemSdk notSupported = matSystemSdk.removeVersions(manifestSystemSdk);
+ if (!notSupported.empty()) {
+ if (error) {
+ *error =
+ "The following System SDK versions are required by device "
+ "compatibility matrix but not supported by the framework manifest: [" +
+ base::Join(notSupported.versions(), ", ") + "]. Supported versions are: [" +
+ base::Join(manifestSystemSdk.versions(), ", ") + "].";
+ }
+ return false;
+ }
+ return true;
+}
+
bool HalManifest::checkCompatibility(const CompatibilityMatrix &mat, std::string *error) const {
if (mType == mat.mType) {
if (error != nullptr) {
@@ -322,6 +340,10 @@
if (!checkVendorNdkCompatibility(mat.device.mVendorNdk, framework.mVendorNdks, error)) {
return false;
}
+
+ if (!checkSystemSdkCompatibility(mat.device.mSystemSdk, framework.mSystemSdk, error)) {
+ return false;
+ }
} else if (mType == SchemaType::DEVICE) {
bool match = false;
for (const auto &range : mat.framework.mSepolicy.sepolicyVersions()) {
@@ -424,7 +446,8 @@
#pragma clang diagnostic ignored "-Wdeprecated-declarations"
lft.framework.mVndks == rgt.framework.mVndks &&
#pragma clang diagnostic pop
- lft.framework.mVendorNdks == rgt.framework.mVendorNdks));
+ lft.framework.mVendorNdks == rgt.framework.mVendorNdks &&
+ lft.framework.mSystemSdk == rgt.framework.mSystemSdk));
}
} // namespace vintf
diff --git a/SystemSdk.cpp b/SystemSdk.cpp
new file mode 100644
index 0000000..d2ee123
--- /dev/null
+++ b/SystemSdk.cpp
@@ -0,0 +1,36 @@
+/*
+ * Copyright (C) 2018 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 "SystemSdk.h"
+
+#include <algorithm>
+
+namespace android {
+namespace vintf {
+
+SystemSdk SystemSdk::removeVersions(const SystemSdk& other) const {
+ SystemSdk ret;
+ std::set_difference(versions().begin(), versions().end(), other.versions().begin(),
+ other.versions().end(), std::inserter(ret.mVersions, ret.mVersions.end()));
+ return ret;
+}
+
+bool SystemSdk::operator==(const SystemSdk& other) const {
+ return versions() == other.versions();
+}
+
+} // namespace vintf
+} // namespace android
diff --git a/include/vintf/CompatibilityMatrix.h b/include/vintf/CompatibilityMatrix.h
index b7a5541..696a0bf 100644
--- a/include/vintf/CompatibilityMatrix.h
+++ b/include/vintf/CompatibilityMatrix.h
@@ -30,6 +30,7 @@
#include "Named.h"
#include "SchemaType.h"
#include "Sepolicy.h"
+#include "SystemSdk.h"
#include "VendorNdk.h"
#include "Vndk.h"
#include "XmlFileGroup.h"
@@ -115,6 +116,7 @@
#pragma clang diagnostic pop
VendorNdk mVendorNdk;
+ SystemSdk mSystemSdk;
} device;
};
diff --git a/include/vintf/HalManifest.h b/include/vintf/HalManifest.h
index 655335e..84bd770 100644
--- a/include/vintf/HalManifest.h
+++ b/include/vintf/HalManifest.h
@@ -28,6 +28,7 @@
#include "ManifestHal.h"
#include "MapValueIterator.h"
#include "SchemaType.h"
+#include "SystemSdk.h"
#include "VendorNdk.h"
#include "Version.h"
#include "Vndk.h"
@@ -158,6 +159,7 @@
#pragma clang diagnostic pop
std::vector<VendorNdk> mVendorNdks;
+ SystemSdk mSystemSdk;
} framework;
};
diff --git a/include/vintf/SystemSdk.h b/include/vintf/SystemSdk.h
new file mode 100644
index 0000000..1828e4a
--- /dev/null
+++ b/include/vintf/SystemSdk.h
@@ -0,0 +1,50 @@
+/*
+ * Copyright (C) 2018 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_SYSTEM_SDK_H
+#define ANDROID_VINTF_SYSTEM_SDK_H
+
+#include <stdint.h>
+
+#include <set>
+#include <string>
+
+namespace android {
+namespace vintf {
+
+// System SDK versions provided for vendor apps.
+class SystemSdk {
+ public:
+ SystemSdk() = default;
+ SystemSdk(std::set<std::string>&& versions) : mVersions(std::move(versions)) {}
+ SystemSdk(const std::set<std::string>& versions) : mVersions(versions) {}
+ const std::set<std::string>& versions() const { return mVersions; }
+ bool empty() const { return versions().empty(); }
+
+ bool operator==(const SystemSdk& other) const;
+ // return {v : v in this and not in other}
+ SystemSdk removeVersions(const SystemSdk& other) const;
+
+ private:
+ friend class AssembleVintfImpl;
+ friend struct SystemSdkConverter;
+ std::set<std::string> mVersions;
+};
+
+} // namespace vintf
+} // namespace android
+
+#endif // ANDROID_VINTF_SYSTEM_SDK_H
diff --git a/include/vintf/parse_string.h b/include/vintf/parse_string.h
index 0bb554a..be0c070 100644
--- a/include/vintf/parse_string.h
+++ b/include/vintf/parse_string.h
@@ -36,6 +36,7 @@
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, KernelSepolicyVersion v);
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);
diff --git a/include/vintf/parse_xml.h b/include/vintf/parse_xml.h
index a92facf..314fb72 100644
--- a/include/vintf/parse_xml.h
+++ b/include/vintf/parse_xml.h
@@ -30,6 +30,7 @@
NO_VNDK = 1 << 3,
NO_KERNEL = 1 << 4,
NO_XMLFILES = 1 << 5,
+ NO_SSDK = 1 << 6,
EVERYTHING = 0,
HALS_ONLY = ~NO_HALS,
diff --git a/parse_xml.cpp b/parse_xml.cpp
index 62ba763..74ba880 100644
--- a/parse_xml.cpp
+++ b/parse_xml.cpp
@@ -741,6 +741,20 @@
const VendorNdkConverter vendorNdkConverter{};
+const XmlTextConverter<std::string> systemSdkVersionConverter{"version"};
+
+struct SystemSdkConverter : public XmlNodeConverter<SystemSdk> {
+ std::string elementName() const override { return "system-sdk"; }
+ void mutateNode(const SystemSdk& object, NodeType* root, DocType* d) const override {
+ appendChildren(root, systemSdkVersionConverter, object.versions(), d);
+ }
+ bool buildObject(SystemSdk* object, NodeType* root) const override {
+ return parseChildren(root, systemSdkVersionConverter, &object->mVersions);
+ }
+};
+
+const SystemSdkConverter systemSdkConverter{};
+
struct HalManifestSepolicyConverter : public XmlNodeConverter<Version> {
std::string elementName() const override { return "sepolicy"; }
void mutateNode(const Version &m, NodeType *root, DocType *d) const override {
@@ -801,6 +815,11 @@
appendChildren(root, vendorNdkConverter, m.framework.mVendorNdks, d);
}
+ if (!(flags & SerializeFlag::NO_SSDK)) {
+ if (!m.framework.mSystemSdk.empty()) {
+ appendChild(root, systemSdkConverter(m.framework.mSystemSdk, d));
+ }
+ }
}
if (!(flags & SerializeFlag::NO_XMLFILES)) {
@@ -846,6 +865,10 @@
if (!parseChildren(root, vendorNdkConverter, &object->framework.mVendorNdks)) {
return false;
}
+
+ if (!parseOptionalChild(root, systemSdkConverter, {}, &object->framework.mSystemSdk)) {
+ return false;
+ }
}
for (auto &&hal : hals) {
std::string description{hal.name};
@@ -949,6 +972,12 @@
appendChild(root, vendorNdkConverter(m.device.mVendorNdk, d));
}
}
+
+ if (!(flags & SerializeFlag::NO_SSDK)) {
+ if (!m.device.mSystemSdk.empty()) {
+ appendChild(root, systemSdkConverter(m.device.mSystemSdk, d));
+ }
+ }
}
if (!(flags & SerializeFlag::NO_XMLFILES)) {
@@ -1000,6 +1029,10 @@
if (!parseOptionalChild(root, vendorNdkConverter, {}, &object->device.mVendorNdk)) {
return false;
}
+
+ if (!parseOptionalChild(root, systemSdkConverter, {}, &object->device.mSystemSdk)) {
+ return false;
+ }
}
if (!kMetaVersion.minorAtLeast(version)) {
diff --git a/test/AssembleVintfTest.cpp b/test/AssembleVintfTest.cpp
index 53a1d0d..4e481ad 100644
--- a/test/AssembleVintfTest.cpp
+++ b/test/AssembleVintfTest.cpp
@@ -356,5 +356,36 @@
EXPECT_TRUE(getInstance()->assemble());
}
+TEST_F(AssembleVintfTest, MatrixSystemSdk) {
+ addInput("compatibility_matrix.xml",
+ "<compatibility-matrix version=\"1.0\" type=\"device\"/>\n");
+ getInstance()->setFakeEnv("BOARD_SYSTEMSDK_VERSIONS", "P 1 2 ");
+ EXPECT_TRUE(getInstance()->assemble());
+ EXPECT_IN(
+ "<compatibility-matrix version=\"1.0\" type=\"device\">\n"
+ " <system-sdk>\n"
+ " <version>1</version>\n"
+ " <version>2</version>\n"
+ " <version>P</version>\n"
+ " </system-sdk>\n"
+ "</compatibility-matrix>\n",
+ getOutput());
+}
+
+TEST_F(AssembleVintfTest, ManifestSystemSdk) {
+ addInput("manifest.xml", "<manifest version=\"1.0\" type=\"framework\"/>\n");
+ getInstance()->setFakeEnv("PRODUCT_SYSTEMSDK_VERSIONS", "P 1 2 ");
+ EXPECT_TRUE(getInstance()->assemble());
+ EXPECT_IN(
+ "<manifest version=\"1.0\" type=\"framework\">\n"
+ " <system-sdk>\n"
+ " <version>1</version>\n"
+ " <version>2</version>\n"
+ " <version>P</version>\n"
+ " </system-sdk>\n"
+ "</manifest>\n",
+ getOutput());
+}
+
} // namespace vintf
} // namespace android
diff --git a/test/LibVintfTest.cpp b/test/LibVintfTest.cpp
index 481897a..e934360 100644
--- a/test/LibVintfTest.cpp
+++ b/test/LibVintfTest.cpp
@@ -2635,6 +2635,82 @@
gHalManifestConverter(manifest, SerializeFlag::HALS_ONLY));
}
+// Make sure missing tags in old VINTF files does not cause incompatibilities.
+TEST_F(LibVintfTest, Empty) {
+ CompatibilityMatrix cm;
+ HalManifest manifest;
+ std::string xml;
+ std::string error;
+
+ xml = "<compatibility-matrix version=\"1.0\" type=\"device\"/>\n";
+ EXPECT_TRUE(gCompatibilityMatrixConverter(&cm, xml))
+ << gCompatibilityMatrixConverter.lastError();
+
+ xml = "<manifest version=\"1.0\" type=\"framework\"/>\n";
+ EXPECT_TRUE(gHalManifestConverter(&manifest, xml)) << gHalManifestConverter.lastError();
+
+ EXPECT_TRUE(manifest.checkCompatibility(cm, &error)) << error;
+}
+
+TEST_F(LibVintfTest, SystemSdk) {
+ CompatibilityMatrix cm;
+ std::string xml;
+ std::string error;
+
+ xml =
+ "<compatibility-matrix version=\"1.0\" type=\"device\">\n"
+ " <system-sdk>\n"
+ " <version>1</version>\n"
+ " <version>P</version>\n"
+ " </system-sdk>\n"
+ "</compatibility-matrix>\n";
+ EXPECT_TRUE(gCompatibilityMatrixConverter(&cm, xml))
+ << gCompatibilityMatrixConverter.lastError();
+ EXPECT_EQ(xml, gCompatibilityMatrixConverter(cm, ~SerializeFlag::NO_SSDK));
+
+ {
+ HalManifest manifest;
+ xml =
+ "<manifest version=\"1.0\" type=\"framework\">\n"
+ " <system-sdk>\n"
+ " <version>1</version>\n"
+ " <version>P</version>\n"
+ " </system-sdk>\n"
+ "</manifest>\n";
+ EXPECT_TRUE(gHalManifestConverter(&manifest, xml)) << gHalManifestConverter.lastError();
+ EXPECT_EQ(xml, gHalManifestConverter(manifest, ~SerializeFlag::NO_SSDK));
+
+ EXPECT_TRUE(manifest.checkCompatibility(cm, &error)) << error;
+ }
+
+ {
+ HalManifest manifest;
+ xml =
+ "<manifest version=\"1.0\" type=\"framework\">\n"
+ " <system-sdk>\n"
+ " <version>1</version>\n"
+ " <version>3</version>\n"
+ " <version>P</version>\n"
+ " </system-sdk>\n"
+ "</manifest>\n";
+ EXPECT_TRUE(gHalManifestConverter(&manifest, xml)) << gHalManifestConverter.lastError();
+ EXPECT_TRUE(manifest.checkCompatibility(cm, &error));
+ }
+
+ {
+ HalManifest manifest;
+ xml =
+ "<manifest version=\"1.0\" type=\"framework\">\n"
+ " <system-sdk>\n"
+ " <version>1</version>\n"
+ " </system-sdk>\n"
+ "</manifest>\n";
+ EXPECT_TRUE(gHalManifestConverter(&manifest, xml)) << gHalManifestConverter.lastError();
+ EXPECT_FALSE(manifest.checkCompatibility(cm, &error));
+ EXPECT_TRUE(error.find("System SDK") != std::string::npos) << error;
+ }
+}
+
} // namespace vintf
} // namespace android