summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorandroid-build-team Robot2018-03-18 02:23:39 -0500
committerandroid-build-team Robot2018-03-18 02:23:39 -0500
commitb1e0a04b45fe9527a037328d8ab3d39ec212fa7d (patch)
tree7921a496c98aa60b353d3e08f57ebde45a896769
parentd6100b32cf1707abf3d2382f4c42a83d0acc3b2a (diff)
parentc5c19bc9f01e1c7c4170f357491795c61afdcd8f (diff)
downloadplatform-system-libvintf-b1e0a04b45fe9527a037328d8ab3d39ec212fa7d.tar.gz
platform-system-libvintf-b1e0a04b45fe9527a037328d8ab3d39ec212fa7d.tar.xz
platform-system-libvintf-b1e0a04b45fe9527a037328d8ab3d39ec212fa7d.zip
Snap for 4662252 from c5c19bc9f01e1c7c4170f357491795c61afdcd8f to pi-release
Change-Id: If43248ec4a03959132951c95cf52f6813bf65149
-rw-r--r--CompatibilityMatrix.cpp68
-rw-r--r--HalManifest.cpp127
-rw-r--r--ManifestHal.cpp66
-rw-r--r--ManifestInstance.cpp39
-rw-r--r--MatrixHal.cpp81
-rw-r--r--MatrixInstance.cpp16
-rw-r--r--VintfObject.cpp33
-rw-r--r--include/vintf/CompatibilityMatrix.h8
-rw-r--r--include/vintf/HalGroup.h28
-rw-r--r--include/vintf/HalManifest.h16
-rw-r--r--include/vintf/ManifestHal.h20
-rw-r--r--include/vintf/ManifestInstance.h15
-rw-r--r--include/vintf/MatrixHal.h16
-rw-r--r--include/vintf/MatrixInstance.h8
-rw-r--r--include/vintf/TransportArch.h11
-rw-r--r--include/vintf/VersionRange.h9
-rw-r--r--include/vintf/parse_string.h2
-rw-r--r--include/vintf/parse_xml.h6
-rw-r--r--parse_string.cpp26
-rw-r--r--parse_xml.cpp37
-rw-r--r--test/AssembleVintfTest.cpp14
-rw-r--r--test/LibVintfTest.cpp273
22 files changed, 685 insertions, 234 deletions
diff --git a/CompatibilityMatrix.cpp b/CompatibilityMatrix.cpp
index bf83a98..3f05881 100644
--- a/CompatibilityMatrix.cpp
+++ b/CompatibilityMatrix.cpp
@@ -75,31 +75,11 @@ std::string CompatibilityMatrix::getXmlSchemaPath(const std::string& xmlFileName
75 return ""; 75 return "";
76} 76}
77 77
78static VersionRange* findRangeWithMajorVersion(std::vector<VersionRange>& versionRanges, 78// Add all package@other_version::interface/instance as an optional instance.
79 size_t majorVer) { 79// If package@this_version::interface/instance is in this (that is, some instance
80 for (VersionRange& vr : versionRanges) { 80// with the same package and interface and instance exists), then other_version is
81 if (vr.majorVer == majorVer) { 81// considered a possible replacement to this_version.
82 return &vr; 82// See LibVintfTest.AddOptionalHal* tests for details.
83 }
84 }
85 return nullptr;
86}
87
88std::pair<MatrixHal*, VersionRange*> CompatibilityMatrix::getHalWithMajorVersion(
89 const std::string& name, size_t majorVer) {
90 for (MatrixHal* hal : getHals(name)) {
91 VersionRange* vr = findRangeWithMajorVersion(hal->versionRanges, majorVer);
92 if (vr != nullptr) {
93 return {hal, vr};
94 }
95 }
96 return {nullptr, nullptr};
97}
98std::pair<const MatrixHal*, const VersionRange*> CompatibilityMatrix::getHalWithMajorVersion(
99 const std::string& name, size_t majorVer) const {
100 return const_cast<CompatibilityMatrix*>(this)->getHalWithMajorVersion(name, majorVer);
101}
102
103bool CompatibilityMatrix::addAllHalsAsOptional(CompatibilityMatrix* other, std::string* error) { 83bool CompatibilityMatrix::addAllHalsAsOptional(CompatibilityMatrix* other, std::string* error) {
104 if (other == nullptr || other->level() <= level()) { 84 if (other == nullptr || other->level() <= level()) {
105 return true; 85 return true;
@@ -108,36 +88,24 @@ bool CompatibilityMatrix::addAllHalsAsOptional(CompatibilityMatrix* other, std::
108 for (auto& pair : other->mHals) { 88 for (auto& pair : other->mHals) {
109 const std::string& name = pair.first; 89 const std::string& name = pair.first;
110 MatrixHal& halToAdd = pair.second; 90 MatrixHal& halToAdd = pair.second;
111 for (const VersionRange& vr : halToAdd.versionRanges) { 91
112 MatrixHal* existingHal; 92 bool added = false;
113 VersionRange* existingVr; 93 for (auto* existingHal : getHals(name)) {
114 std::tie(existingHal, existingVr) = getHalWithMajorVersion(name, vr.majorVer); 94 if (existingHal->containsInstances(halToAdd)) {
115 95 existingHal->insertVersionRanges(halToAdd);
116 if (existingHal == nullptr) { 96 added = true;
117 MatrixHal optionalHalToAdd(halToAdd); 97 // Do not break here; try other <hal> with the same name as well.
118 optionalHalToAdd.optional = true;
119 optionalHalToAdd.versionRanges = {vr};
120 if (!add(std::move(optionalHalToAdd))) {
121 if (error) {
122 *error = "Cannot add HAL " + name + " for unknown reason.";
123 }
124 return false;
125 }
126 continue;
127 } 98 }
99 }
128 100
129 if (!existingHal->optional && !existingHal->containsInstances(halToAdd)) { 101 if (!added) {
130 if (error != nullptr) { 102 halToAdd.setOptional(true);
131 *error = "HAL " + toFQNameString(name, vr.minVer()) + " is a required " + 103 if (!add(std::move(halToAdd))) {
132 "HAL, but fully qualified instance names don't match (at FCM " 104 if (error) {
133 "Version " + 105 *error = "Cannot add HAL " + name + " for unknown reason.";
134 std::to_string(level()) + " and " + std::to_string(other->level()) +
135 ")";
136 } 106 }
137 return false; 107 return false;
138 } 108 }
139
140 existingVr->maxMinor = std::max(existingVr->maxMinor, vr.maxMinor);
141 } 109 }
142 } 110 }
143 return true; 111 return true;
diff --git a/HalManifest.cpp b/HalManifest.cpp
index a27e935..aee4462 100644
--- a/HalManifest.cpp
+++ b/HalManifest.cpp
@@ -177,13 +177,6 @@ std::set<Version> HalManifest::getSupportedVersions(const std::string &name) con
177 return ret; 177 return ret;
178} 178}
179 179
180bool HalManifest::hasInstance(const std::string& halName, const Version& version,
181 const std::string& interfaceName,
182 const std::string& instanceName) const {
183 const auto& instances = getInstances(halName, version, interfaceName);
184 return instances.find(instanceName) != instances.end();
185}
186
187bool HalManifest::forEachInstanceOfVersion( 180bool HalManifest::forEachInstanceOfVersion(
188 const std::string& package, const Version& expectVersion, 181 const std::string& package, const Version& expectVersion,
189 const std::function<bool(const ManifestInstance&)>& func) const { 182 const std::function<bool(const ManifestInstance&)>& func) const {
@@ -199,89 +192,12 @@ bool HalManifest::forEachInstanceOfVersion(
199 return true; 192 return true;
200} 193}
201 194
202static bool satisfyVersion(const MatrixHal& matrixHal, const Version& manifestHalVersion) {
203 for (const VersionRange &matrixVersionRange : matrixHal.versionRanges) {
204 // If Compatibility Matrix says 2.5-2.7, the "2.7" is purely informational;
205 // the framework can work with all 2.5-2.infinity.
206 if (matrixVersionRange.supportedBy(manifestHalVersion)) {
207 return true;
208 }
209 }
210 return false;
211}
212
213// Check if matrixHal.interfaces is a subset of instancesOfVersion
214static bool satisfyAllInstances(const MatrixHal& matrixHal,
215 const InstancesOfVersion &instancesOfVersion) {
216 for (const auto& matrixHalInterfacePair : matrixHal.interfaces) {
217 const std::string& interface = matrixHalInterfacePair.first;
218 auto it = instancesOfVersion.find(interface);
219 if (it == instancesOfVersion.end()) {
220 return false;
221 }
222 const std::set<std::string>& manifestInterfaceInstances = it->second;
223 const std::set<std::string>& matrixInterfaceInstances =
224 matrixHalInterfacePair.second.instances;
225 if (!std::includes(manifestInterfaceInstances.begin(), manifestInterfaceInstances.end(),
226 matrixInterfaceInstances.begin(), matrixInterfaceInstances.end())) {
227 return false;
228 }
229 }
230 return true;
231}
232
233Instances HalManifest::expandInstances(const std::string& name) const {
234 Instances instances;
235 // Do the cross product version x interface x instance and sort them,
236 // because interfaces / instances can span in multiple HALs.
237 // This is efficient for small <hal> entries.
238 for (const ManifestHal* manifestHal : getHals(name)) {
239 for (const Version& manifestHalVersion : manifestHal->versions) {
240 instances[manifestHalVersion] = {};
241 for (const auto& halInterfacePair : manifestHal->interfaces) {
242 const std::string& interface = halInterfacePair.first;
243 const auto& toAdd = halInterfacePair.second.instances;
244 instances[manifestHalVersion][interface].insert(toAdd.begin(), toAdd.end());
245 }
246 }
247 }
248 return instances;
249}
250
251bool HalManifest::isCompatible(const Instances& instances, const MatrixHal& matrixHal) const {
252 for (const auto& instanceMapPair : instances) {
253 const Version& manifestHalVersion = instanceMapPair.first;
254 const InstancesOfVersion& instancesOfVersion = instanceMapPair.second;
255 if (!satisfyVersion(matrixHal, manifestHalVersion)) {
256 continue;
257 }
258 if (!satisfyAllInstances(matrixHal, instancesOfVersion)) {
259 continue;
260 }
261 return true; // match!
262 }
263 return false;
264}
265
266static std::vector<std::string> toLines(const Instances& allInstances) {
267 std::vector<std::string> lines;
268 for (const auto& pair : allInstances) {
269 const auto& version = pair.first;
270 for (const auto& ifacePair : pair.second) {
271 const auto& interface = ifacePair.first;
272 for (const auto& instance : ifacePair.second) {
273 lines.push_back(toFQNameString(version, interface, instance));
274 }
275 }
276 }
277 return lines;
278}
279
280// indent = 2, {"foo"} => "foo" 195// indent = 2, {"foo"} => "foo"
281// indent = 2, {"foo", "bar"} => "\n foo\n bar"; 196// indent = 2, {"foo", "bar"} => "\n foo\n bar";
282void multilineIndent(std::ostream& os, size_t indent, const std::vector<std::string>& lines) { 197template <typename Container>
198void multilineIndent(std::ostream& os, size_t indent, const Container& lines) {
283 if (lines.size() == 1) { 199 if (lines.size() == 1) {
284 os << lines.front(); 200 os << *lines.begin();
285 return; 201 return;
286 } 202 }
287 for (const auto& line : lines) { 203 for (const auto& line : lines) {
@@ -298,13 +214,29 @@ std::vector<std::string> HalManifest::checkIncompatibleHals(const CompatibilityM
298 if (matrixHal.optional) { 214 if (matrixHal.optional) {
299 continue; 215 continue;
300 } 216 }
301 auto manifestInstances = expandInstances(matrixHal.name); 217
302 if (!isCompatible(manifestInstances, matrixHal)) { 218 std::set<FqInstance> manifestInstances;
219 std::set<FqInstance> manifestInstancesNoPackage;
220 std::set<Version> versions;
221 for (const ManifestHal* manifestHal : getHals(matrixHal.name)) {
222 manifestHal->forEachInstance([&](const auto& manifestInstance) {
223 manifestInstances.insert(manifestInstance.getFqInstance());
224 manifestInstancesNoPackage.insert(manifestInstance.getFqInstanceNoPackage());
225 return true;
226 });
227 manifestHal->appendAllVersions(&versions);
228 }
229
230 if (!matrixHal.isCompatible(manifestInstances, versions)) {
303 std::ostringstream oss; 231 std::ostringstream oss;
304 oss << matrixHal.name << ":\n required: "; 232 oss << matrixHal.name << ":\n required: ";
305 multilineIndent(oss, 8, android::vintf::expandInstances(matrixHal)); 233 multilineIndent(oss, 8, android::vintf::expandInstances(matrixHal));
306 oss << "\n provided: "; 234 oss << "\n provided: ";
307 multilineIndent(oss, 8, toLines(manifestInstances)); 235 if (manifestInstances.empty()) {
236 multilineIndent(oss, 8, versions);
237 } else {
238 multilineIndent(oss, 8, manifestInstancesNoPackage);
239 }
308 240
309 ret.insert(ret.end(), oss.str()); 241 ret.insert(ret.end(), oss.str());
310 } 242 }
@@ -312,6 +244,21 @@ std::vector<std::string> HalManifest::checkIncompatibleHals(const CompatibilityM
312 return ret; 244 return ret;
313} 245}
314 246
247std::set<std::string> HalManifest::checkUnusedHals(const CompatibilityMatrix& mat) const {
248 std::set<std::string> ret;
249
250 forEachInstance([&ret, &mat](const auto& manifestInstance) {
251 const auto& fqInstance = manifestInstance.getFqInstance();
252 if (!mat.hasInstance(fqInstance.getPackage(), fqInstance.getVersion(),
253 fqInstance.getInterface(), fqInstance.getInstance())) {
254 ret.insert(fqInstance.string());
255 }
256 return true;
257 });
258
259 return ret;
260}
261
315static bool checkVendorNdkCompatibility(const VendorNdk& matVendorNdk, 262static bool checkVendorNdkCompatibility(const VendorNdk& matVendorNdk,
316 const std::vector<VendorNdk>& manifestVendorNdk, 263 const std::vector<VendorNdk>& manifestVendorNdk,
317 std::string* error) { 264 std::string* error) {
diff --git a/ManifestHal.cpp b/ManifestHal.cpp
index aa9d358..1576c80 100644
--- a/ManifestHal.cpp
+++ b/ManifestHal.cpp
@@ -18,6 +18,7 @@
18#include <unordered_set> 18#include <unordered_set>
19 19
20#include "MapValueIterator.h" 20#include "MapValueIterator.h"
21#include "parse_string.h"
21 22
22namespace android { 23namespace android {
23namespace vintf { 24namespace vintf {
@@ -40,12 +41,14 @@ bool ManifestHal::operator==(const ManifestHal &other) const {
40 return false; 41 return false;
41 if (versions != other.versions) 42 if (versions != other.versions)
42 return false; 43 return false;
43 // do not compare impl 44 if (!(transportArch == other.transportArch)) return false;
45 if (interfaces != other.interfaces) return false;
46 if (isOverride() != other.isOverride()) return false;
47 if (mAdditionalInstances != other.mAdditionalInstances) return false;
44 return true; 48 return true;
45} 49}
46 50
47bool ManifestHal::forEachInstance(const std::function<bool(const ManifestInstance&)>& func) const { 51bool ManifestHal::forEachInstance(const std::function<bool(const ManifestInstance&)>& func) const {
48 // TODO(b/73556059): support <fqname> as well.
49 for (const auto& v : versions) { 52 for (const auto& v : versions) {
50 for (const auto& intf : iterateValues(interfaces)) { 53 for (const auto& intf : iterateValues(interfaces)) {
51 for (const auto& instance : intf.instances) { 54 for (const auto& instance : intf.instances) {
@@ -60,6 +63,13 @@ bool ManifestHal::forEachInstance(const std::function<bool(const ManifestInstanc
60 } 63 }
61 } 64 }
62 } 65 }
66
67 for (const auto& manifestInstance : mAdditionalInstances) {
68 if (!func(manifestInstance)) {
69 return false;
70 }
71 }
72
63 return true; 73 return true;
64} 74}
65 75
@@ -73,5 +83,57 @@ bool ManifestHal::isDisabledHal() const {
73 return !hasInstance; 83 return !hasInstance;
74} 84}
75 85
86void ManifestHal::appendAllVersions(std::set<Version>* ret) const {
87 ret->insert(versions.begin(), versions.end());
88 forEachInstance([&](const auto& e) {
89 ret->insert(e.version());
90 return true;
91 });
92}
93
94static bool verifyInstances(const std::set<FqInstance>& fqInstances, std::string* error) {
95 for (const FqInstance& fqInstance : fqInstances) {
96 if (fqInstance.hasPackage()) {
97 if (error) *error = "Should not specify package: \"" + fqInstance.string() + "\"";
98 return false;
99 }
100 if (!fqInstance.hasVersion()) {
101 if (error) *error = "Should specify version: \"" + fqInstance.string() + "\"";
102 return false;
103 }
104 if (!fqInstance.hasInterface()) {
105 if (error) *error = "Should specify interface: \"" + fqInstance.string() + "\"";
106 return false;
107 }
108 if (!fqInstance.hasInstance()) {
109 if (error) *error = "Should specify instance: \"" + fqInstance.string() + "\"";
110 return false;
111 }
112 }
113 return true;
114}
115
116bool ManifestHal::insertInstances(const std::set<FqInstance>& fqInstances, std::string* error) {
117 if (!verifyInstances(fqInstances, error)) {
118 return false;
119 }
120
121 for (const FqInstance& e : fqInstances) {
122 FqInstance withPackage;
123 if (!withPackage.setTo(this->getName(), e.getMajorVersion(), e.getMinorVersion(),
124 e.getInterface(), e.getInstance())) {
125 if (error) {
126 *error = "Cannot create FqInstance with package='" + this->getName() +
127 "', version='" + to_string(Version(e.getVersion())) + "', interface='" +
128 e.getInterface() + "', instance='" + e.getInstance() + "'";
129 }
130 return false;
131 }
132 mAdditionalInstances.emplace(std::move(withPackage), this->transportArch);
133 }
134
135 return true;
136}
137
76} // namespace vintf 138} // namespace vintf
77} // namespace android 139} // namespace android
diff --git a/ManifestInstance.cpp b/ManifestInstance.cpp
index 66e0cd3..7a216eb 100644
--- a/ManifestInstance.cpp
+++ b/ManifestInstance.cpp
@@ -14,6 +14,11 @@
14 * limitations under the License. 14 * limitations under the License.
15 */ 15 */
16 16
17#ifndef LIBVINTF_TARGET
18#define LOG_TAG "libvintf"
19#include <android-base/logging.h>
20#endif
21
17#include "ManifestInstance.h" 22#include "ManifestInstance.h"
18 23
19#include <utility> 24#include <utility>
@@ -21,6 +26,16 @@
21namespace android { 26namespace android {
22namespace vintf { 27namespace vintf {
23 28
29ManifestInstance::ManifestInstance() = default;
30
31ManifestInstance::ManifestInstance(const ManifestInstance&) = default;
32
33ManifestInstance::ManifestInstance(ManifestInstance&&) = default;
34
35ManifestInstance& ManifestInstance::operator=(const ManifestInstance&) = default;
36
37ManifestInstance& ManifestInstance::operator=(ManifestInstance&&) = default;
38
24ManifestInstance::ManifestInstance(FqInstance&& fqInstance, TransportArch&& ta) 39ManifestInstance::ManifestInstance(FqInstance&& fqInstance, TransportArch&& ta)
25 : mFqInstance(std::move(fqInstance)), mTransportArch(std::move(ta)) {} 40 : mFqInstance(std::move(fqInstance)), mTransportArch(std::move(ta)) {}
26ManifestInstance::ManifestInstance(const FqInstance& fqInstance, const TransportArch& ta) 41ManifestInstance::ManifestInstance(const FqInstance& fqInstance, const TransportArch& ta)
@@ -50,5 +65,29 @@ Arch ManifestInstance::arch() const {
50 return mTransportArch.arch; 65 return mTransportArch.arch;
51} 66}
52 67
68const FqInstance& ManifestInstance::getFqInstance() const {
69 return mFqInstance;
70}
71
72bool ManifestInstance::operator==(const ManifestInstance& other) const {
73 return mFqInstance == other.mFqInstance && mTransportArch == other.mTransportArch;
74}
75bool ManifestInstance::operator<(const ManifestInstance& other) const {
76 if (mFqInstance < other.mFqInstance) return true;
77 if (other.mFqInstance < mFqInstance) return false;
78 return mTransportArch < other.mTransportArch;
79}
80
81FqInstance ManifestInstance::getFqInstanceNoPackage() const {
82 FqInstance e;
83 bool success = e.setTo(version().majorVer, version().minorVer, interface(), instance());
84#ifndef LIBVINTF_TARGET
85 CHECK(success) << "Cannot remove package from '" << mFqInstance.string() << "'";
86#else
87 (void)success;
88#endif
89 return e;
90}
91
53} // namespace vintf 92} // namespace vintf
54} // namespace android 93} // namespace android
diff --git a/MatrixHal.cpp b/MatrixHal.cpp
index fbe9a5f..504265e 100644
--- a/MatrixHal.cpp
+++ b/MatrixHal.cpp
@@ -16,6 +16,8 @@
16 16
17#include "MatrixHal.h" 17#include "MatrixHal.h"
18 18
19#include <algorithm>
20
19#include "MapValueIterator.h" 21#include "MapValueIterator.h"
20 22
21namespace android { 23namespace android {
@@ -70,14 +72,22 @@ bool MatrixHal::containsInstances(const MatrixHal& other) const {
70 72
71bool MatrixHal::forEachInstance(const std::function<bool(const MatrixInstance&)>& func) const { 73bool MatrixHal::forEachInstance(const std::function<bool(const MatrixInstance&)>& func) const {
72 for (const auto& vr : versionRanges) { 74 for (const auto& vr : versionRanges) {
73 for (const auto& intf : iterateValues(interfaces)) { 75 if (!forEachInstance(vr, func)) {
74 for (const auto& instance : intf.instances) { 76 return false;
75 // TODO(b/73556059): Store MatrixInstance as well to avoid creating temps 77 }
76 FqInstance fqInstance; 78 }
77 if (fqInstance.setTo(getName(), vr.majorVer, vr.minMinor, intf.name, instance)) { 79 return true;
78 if (!func(MatrixInstance(std::move(fqInstance), VersionRange(vr), optional))) { 80}
79 return false; 81
80 } 82bool MatrixHal::forEachInstance(const VersionRange& vr,
83 const std::function<bool(const MatrixInstance&)>& func) const {
84 for (const auto& intf : iterateValues(interfaces)) {
85 for (const auto& instance : intf.instances) {
86 // TODO(b/73556059): Store MatrixInstance as well to avoid creating temps
87 FqInstance fqInstance;
88 if (fqInstance.setTo(getName(), vr.majorVer, vr.minMinor, intf.name, instance)) {
89 if (!func(MatrixInstance(std::move(fqInstance), VersionRange(vr), optional))) {
90 return false;
81 } 91 }
82 } 92 }
83 } 93 }
@@ -85,5 +95,60 @@ bool MatrixHal::forEachInstance(const std::function<bool(const MatrixInstance&)>
85 return true; 95 return true;
86} 96}
87 97
98bool MatrixHal::isCompatible(const std::set<FqInstance>& providedInstances,
99 const std::set<Version>& providedVersions) const {
100 // <version>'s are related by OR.
101 return std::any_of(versionRanges.begin(), versionRanges.end(), [&](const VersionRange& vr) {
102 return isCompatible(vr, providedInstances, providedVersions);
103 });
104}
105
106bool MatrixHal::isCompatible(const VersionRange& vr, const std::set<FqInstance>& providedInstances,
107 const std::set<Version>& providedVersions) const {
108 bool hasAnyInstance = false;
109 bool versionUnsatisfied = false;
110
111 // Look at each interface/instance, and ensure that they are in providedInstances.
112 forEachInstance(vr, [&](const MatrixInstance& matrixInstance) {
113 hasAnyInstance = true;
114
115 versionUnsatisfied |=
116 !std::any_of(providedInstances.begin(), providedInstances.end(),
117 [&](const FqInstance& providedInstance) {
118 return matrixInstance.isSatisfiedBy(providedInstance);
119 });
120
121 return !versionUnsatisfied; // if any interface/instance is unsatisfied, break
122 });
123
124 if (hasAnyInstance) {
125 return !versionUnsatisfied;
126 }
127
128 // In some cases (e.g. tests and native HALs), compatibility matrix doesn't specify
129 // any instances. Check versions only.
130 return std::any_of(
131 providedVersions.begin(), providedVersions.end(),
132 [&](const auto& providedVersion) { return vr.supportedBy(providedVersion); });
133}
134
135void MatrixHal::setOptional(bool o) {
136 this->optional = o;
137}
138
139void MatrixHal::insertVersionRanges(const MatrixHal& other) {
140 for (const VersionRange& otherVr : other.versionRanges) {
141 auto existingVr = std::find_if(this->versionRanges.begin(), this->versionRanges.end(),
142 [&](const auto& e) { return e.overlaps(otherVr); });
143
144 if (existingVr == this->versionRanges.end()) {
145 this->versionRanges.push_back(otherVr);
146 } else {
147 existingVr->minMinor = std::min(existingVr->minMinor, otherVr.minMinor);
148 existingVr->maxMinor = std::max(existingVr->maxMinor, otherVr.maxMinor);
149 }
150 }
151}
152
88} // namespace vintf 153} // namespace vintf
89} // namespace android 154} // namespace android
diff --git a/MatrixInstance.cpp b/MatrixInstance.cpp
index 46c92e0..0ac3681 100644
--- a/MatrixInstance.cpp
+++ b/MatrixInstance.cpp
@@ -21,6 +21,16 @@
21namespace android { 21namespace android {
22namespace vintf { 22namespace vintf {
23 23
24MatrixInstance::MatrixInstance() = default;
25
26MatrixInstance::MatrixInstance(const MatrixInstance&) = default;
27
28MatrixInstance::MatrixInstance(MatrixInstance&&) = default;
29
30MatrixInstance& MatrixInstance::operator=(const MatrixInstance&) = default;
31
32MatrixInstance& MatrixInstance::operator=(MatrixInstance&&) = default;
33
24MatrixInstance::MatrixInstance(FqInstance&& fqInstance, VersionRange&& range, bool optional) 34MatrixInstance::MatrixInstance(FqInstance&& fqInstance, VersionRange&& range, bool optional)
25 : mFqInstance(std::move(fqInstance)), mRange(std::move(range)), mOptional(optional) {} 35 : mFqInstance(std::move(fqInstance)), mRange(std::move(range)), mOptional(optional) {}
26 36
@@ -48,5 +58,11 @@ bool MatrixInstance::optional() const {
48 return mOptional; 58 return mOptional;
49} 59}
50 60
61bool MatrixInstance::isSatisfiedBy(const FqInstance& provided) const {
62 return package() == provided.getPackage() &&
63 versionRange().supportedBy(provided.getVersion()) &&
64 interface() == provided.getInterface() && instance() == provided.getInstance();
65}
66
51} // namespace vintf 67} // namespace vintf
52} // namespace android 68} // namespace android
diff --git a/VintfObject.cpp b/VintfObject.cpp
index 5c329fa..88bcce2 100644
--- a/VintfObject.cpp
+++ b/VintfObject.cpp
@@ -606,38 +606,35 @@ bool VintfObject::isInstanceDeprecated(const std::string& package, Version versi
606 isInstanceInUse(package, version, interface, instance); 606 isInstanceInUse(package, version, interface, instance);
607 if (oldVersionIsServed) { 607 if (oldVersionIsServed) {
608 // Find any package@x.? in target matrix, and check if instance is in target matrix. 608 // Find any package@x.? in target matrix, and check if instance is in target matrix.
609 const MatrixHal* targetMatrixHal; 609 bool foundInstance = false;
610 const VersionRange* targetMatrixRange; 610 Version targetMatrixMinVer;
611 std::tie(targetMatrixHal, targetMatrixRange) = 611 targetMatrix.forEachInstanceOfPackage(package, [&](const auto& targetMatrixInstance) {
612 targetMatrix.getHalWithMajorVersion(package, version.majorVer); 612 if (targetMatrixInstance.versionRange().majorVer == version.majorVer &&
613 if (targetMatrixHal == nullptr || targetMatrixRange == nullptr) { 613 targetMatrixInstance.interface() == interface &&
614 targetMatrixInstance.instance() == instance) {
615 targetMatrixMinVer = targetMatrixInstance.versionRange().minVer();
616 foundInstance = true;
617 }
618 return !foundInstance; // continue if not found
619 });
620 if (!foundInstance) {
614 if (error) { 621 if (error) {
615 *error = toFQNameString(package, servedVersion) + 622 *error = toFQNameString(package, servedVersion, interface, instance) +
616 " is deprecated in compatibility matrix at FCM Version " + 623 " is deprecated in compatibility matrix at FCM Version " +
617 to_string(targetMatrix.level()) + "; it should not be served."; 624 to_string(targetMatrix.level()) + "; it should not be served.";
618 } 625 }
619 return true; 626 return true;
620 } 627 }
621 628
622 const auto& targetMatrixInstances = targetMatrixHal->getInstances(interface);
623 if (targetMatrixInstances.find(instance) == targetMatrixInstances.end()) {
624 if (error) {
625 *error += toFQNameString(package, servedVersion, interface, instance) +
626 " is deprecated at FCM version " + to_string(targetMatrix.level()) +
627 "; it should be not be served.\n";
628 }
629 return true;
630 }
631
632 // Assuming that targetMatrix requires @x.u-v, require that at least @x.u is served. 629 // Assuming that targetMatrix requires @x.u-v, require that at least @x.u is served.
633 bool targetVersionServed; 630 bool targetVersionServed;
634 std::tie(targetVersionServed, std::ignore) = 631 std::tie(targetVersionServed, std::ignore) =
635 isInstanceInUse(package, targetMatrixRange->minVer(), interface, instance); 632 isInstanceInUse(package, targetMatrixMinVer, interface, instance);
636 633
637 if (!targetVersionServed) { 634 if (!targetVersionServed) {
638 if (error) { 635 if (error) {
639 *error += toFQNameString(package, servedVersion) + " is deprecated; " + 636 *error += toFQNameString(package, servedVersion) + " is deprecated; " +
640 "require at least " + to_string(targetMatrixRange->minVer()) + "\n"; 637 "require at least " + to_string(targetMatrixMinVer) + "\n";
641 } 638 }
642 return true; 639 return true;
643 } 640 }
diff --git a/include/vintf/CompatibilityMatrix.h b/include/vintf/CompatibilityMatrix.h
index e31917f..6431836 100644
--- a/include/vintf/CompatibilityMatrix.h
+++ b/include/vintf/CompatibilityMatrix.h
@@ -71,13 +71,7 @@ struct CompatibilityMatrix : public HalGroup<MatrixHal>, public XmlFileGroup<Mat
71 // from "other". 71 // from "other".
72 // Require other->level() > this->level(), otherwise do nothing. 72 // Require other->level() > this->level(), otherwise do nothing.
73 bool addAllHalsAsOptional(CompatibilityMatrix* other, std::string* error); 73 bool addAllHalsAsOptional(CompatibilityMatrix* other, std::string* error);
74 // Return the MatrixHal object with the given name and major version. Since all major 74
75 // version are guaranteed distinct when add()-ed, there should be at most 1 match.
76 // Return nullptr if none is found.
77 std::pair<MatrixHal*, VersionRange*> getHalWithMajorVersion(const std::string& name,
78 size_t majorVer);
79 std::pair<const MatrixHal*, const VersionRange*> getHalWithMajorVersion(const std::string& name,
80 size_t majorVer) const;
81 // Similar to addAllHalsAsOptional but on <xmlfile> entries. 75 // Similar to addAllHalsAsOptional but on <xmlfile> entries.
82 bool addAllXmlFilesAsOptional(CompatibilityMatrix* other, std::string* error); 76 bool addAllXmlFilesAsOptional(CompatibilityMatrix* other, std::string* error);
83 77
diff --git a/include/vintf/HalGroup.h b/include/vintf/HalGroup.h
index bb84423..033adf0 100644
--- a/include/vintf/HalGroup.h
+++ b/include/vintf/HalGroup.h
@@ -20,8 +20,6 @@
20#include <map> 20#include <map>
21#include <set> 21#include <set>
22 22
23#include <hidl-util/FqInstance.h>
24
25#include "MapValueIterator.h" 23#include "MapValueIterator.h"
26#include "Version.h" 24#include "Version.h"
27 25
@@ -61,7 +59,7 @@ struct HalGroup {
61 59
62 // Get all hals with the given name (e.g "android.hardware.camera"). 60 // Get all hals with the given name (e.g "android.hardware.camera").
63 // There could be multiple hals that matches the same given name. 61 // There could be multiple hals that matches the same given name.
64 // TODO(b/74247301) Deprecated; use forEachInstance instead. 62 // TODO(b/74247301) Deprecated; use forEachInstanceOfPackage instead.
65 std::vector<const Hal*> getHals(const std::string& name) const { 63 std::vector<const Hal*> getHals(const std::string& name) const {
66 std::vector<const Hal*> ret; 64 std::vector<const Hal*> ret;
67 auto range = mHals.equal_range(name); 65 auto range = mHals.equal_range(name);
@@ -74,7 +72,7 @@ struct HalGroup {
74 // Get all hals with the given name (e.g "android.hardware.camera"). 72 // Get all hals with the given name (e.g "android.hardware.camera").
75 // There could be multiple hals that matches the same given name. 73 // There could be multiple hals that matches the same given name.
76 // Non-const version of the above getHals() method. 74 // Non-const version of the above getHals() method.
77 // TODO(b/74247301) Deprecated; use forEachInstance instead. 75 // TODO(b/74247301) Deprecated; use forEachInstanceOfPackage instead.
78 std::vector<Hal*> getHals(const std::string& name) { 76 std::vector<Hal*> getHals(const std::string& name) {
79 std::vector<Hal*> ret; 77 std::vector<Hal*> ret;
80 auto range = mHals.equal_range(name); 78 auto range = mHals.equal_range(name);
@@ -93,6 +91,16 @@ struct HalGroup {
93 return true; 91 return true;
94 } 92 }
95 93
94 bool forEachInstanceOfPackage(const std::string& package,
95 const std::function<bool(const InstanceType&)>& func) const {
96 for (const auto* hal : getHals(package)) {
97 if (!hal->forEachInstance(func)) {
98 return false;
99 }
100 }
101 return true;
102 }
103
96 // Apply func to all instances of package@expectVersion::*/*. 104 // Apply func to all instances of package@expectVersion::*/*.
97 // For example, if a.h.foo@1.1::IFoo/default is in "this" and getFqInstances 105 // For example, if a.h.foo@1.1::IFoo/default is in "this" and getFqInstances
98 // is called with a.h.foo@1.0, then a.h.foo@1.1::IFoo/default is returned. 106 // is called with a.h.foo@1.0, then a.h.foo@1.1::IFoo/default is returned.
@@ -145,6 +153,18 @@ struct HalGroup {
145 return ret; 153 return ret;
146 } 154 }
147 155
156 // Return whether instance is in getInstances(...).
157 bool hasInstance(const std::string& halName, const Version& version,
158 const std::string& interfaceName, const std::string& instance) const {
159 bool found = false;
160 (void)forEachInstanceOfInterface(halName, version, interfaceName,
161 [&found, &instance](const auto& e) {
162 found |= (instance == e.instance());
163 return !found; // if not found, continue
164 });
165 return found;
166 }
167
148 protected: 168 protected:
149 // sorted map from component name to the component. 169 // sorted map from component name to the component.
150 // The component name looks like: android.hardware.foo 170 // The component name looks like: android.hardware.foo
diff --git a/include/vintf/HalManifest.h b/include/vintf/HalManifest.h
index 71f7017..0e77142 100644
--- a/include/vintf/HalManifest.h
+++ b/include/vintf/HalManifest.h
@@ -18,7 +18,6 @@
18#ifndef ANDROID_VINTF_HAL_MANIFEST_H 18#ifndef ANDROID_VINTF_HAL_MANIFEST_H
19#define ANDROID_VINTF_HAL_MANIFEST_H 19#define ANDROID_VINTF_HAL_MANIFEST_H
20 20
21#include <hidl-util/FqInstance.h>
22#include <utils/Errors.h> 21#include <utils/Errors.h>
23#include <map> 22#include <map>
24#include <string> 23#include <string>
@@ -71,10 +70,6 @@ struct HalManifest : public HalGroup<ManifestHal>, public XmlFileGroup<ManifestX
71 // (dupes removed) 70 // (dupes removed)
72 std::set<Version> getSupportedVersions(const std::string &name) const; 71 std::set<Version> getSupportedVersions(const std::string &name) const;
73 72
74 // Convenience method for checking if instanceName is in getInstances(halName, interfaceName)
75 bool hasInstance(const std::string& halName, const Version& version,
76 const std::string& interfaceName, const std::string& instanceName) const;
77
78 // Check compatibility against a compatibility matrix. Considered compatible if 73 // Check compatibility against a compatibility matrix. Considered compatible if
79 // - framework manifest vs. device compat-mat 74 // - framework manifest vs. device compat-mat
80 // - checkIncompatibility for HALs returns only optional HALs 75 // - checkIncompatibility for HALs returns only optional HALs
@@ -142,12 +137,21 @@ struct HalManifest : public HalGroup<ManifestHal>, public XmlFileGroup<ManifestX
142 // Check if all instances in matrixHal is supported in this manifest. 137 // Check if all instances in matrixHal is supported in this manifest.
143 bool isCompatible(const details::Instances& instances, const MatrixHal& matrixHal) const; 138 bool isCompatible(const details::Instances& instances, const MatrixHal& matrixHal) const;
144 139
145 // Return a list of instance names that does NOT conform to 140 // Return a list of error messages (for each <hal> name) that does NOT conform to
146 // the given compatibility matrix. It does not contain components that are optional. 141 // the given compatibility matrix. It does not contain components that are optional.
142 // That is, return empty list iff
143 // (instance in matrix) => (instance in manifest).
147 std::vector<std::string> checkIncompatibleHals(const CompatibilityMatrix& mat) const; 144 std::vector<std::string> checkIncompatibleHals(const CompatibilityMatrix& mat) const;
148 145
149 void removeHals(const std::string& name, size_t majorVer); 146 void removeHals(const std::string& name, size_t majorVer);
150 147
148 // Returns a list of instance names that are in this manifest but
149 // are not specified in the given matrix, whether the HAL is specified as an optional or
150 // required HAL.
151 // That is, return empty list iff
152 // (instance in manifest) => (instance in matrix).
153 std::set<std::string> checkUnusedHals(const CompatibilityMatrix& mat) const;
154
151 SchemaType mType; 155 SchemaType mType;
152 Level mLevel = Level::UNSPECIFIED; 156 Level mLevel = Level::UNSPECIFIED;
153 // version attribute. Default is 1.0 for manifests created programatically. 157 // version attribute. Default is 1.0 for manifests created programatically.
diff --git a/include/vintf/ManifestHal.h b/include/vintf/ManifestHal.h
index 36b173e..026c7a5 100644
--- a/include/vintf/ManifestHal.h
+++ b/include/vintf/ManifestHal.h
@@ -23,6 +23,8 @@
23#include <string> 23#include <string>
24#include <vector> 24#include <vector>
25 25
26#include <hidl-util/FqInstance.h>
27
26#include "HalFormat.h" 28#include "HalFormat.h"
27#include "HalInterface.h" 29#include "HalInterface.h"
28#include "ManifestInstance.h" 30#include "ManifestInstance.h"
@@ -47,10 +49,6 @@ struct ManifestHal {
47 interfaces(std::move(intf)) {} 49 interfaces(std::move(intf)) {}
48 50
49 bool operator==(const ManifestHal &other) const; 51 bool operator==(const ManifestHal &other) const;
50 // Check whether the ManifestHal contains the given version.
51 // E.g. if hal has version "1.0" and "2.1", it contains version
52 // "1.0", "2.0", "2.1".
53 bool containsVersion(const Version& version) const;
54 52
55 HalFormat format = HalFormat::HIDL; 53 HalFormat format = HalFormat::HIDL;
56 std::string name; 54 std::string name;
@@ -58,9 +56,6 @@ struct ManifestHal {
58 TransportArch transportArch; 56 TransportArch transportArch;
59 std::map<std::string, HalInterface> interfaces; 57 std::map<std::string, HalInterface> interfaces;
60 58
61 inline bool hasInterface(const std::string& interface_name) const {
62 return interfaces.find(interface_name) != interfaces.end();
63 }
64 inline Transport transport() const { 59 inline Transport transport() const {
65 return transportArch.transport; 60 return transportArch.transport;
66 } 61 }
@@ -85,7 +80,18 @@ struct ManifestHal {
85 // (constructed via ManifestHal()) is valid. 80 // (constructed via ManifestHal()) is valid.
86 bool isValid() const; 81 bool isValid() const;
87 82
83 // Return all versions mentioned by <version>s and <fqname>s.
84 void appendAllVersions(std::set<Version>* ret) const;
85
88 bool mIsOverride = false; 86 bool mIsOverride = false;
87 // Additional instances to <version> x <interface> x <instance>.
88 std::set<ManifestInstance> mAdditionalInstances;
89
90 // insert instances to mAdditionalInstances.
91 // Existing instances will be ignored.
92 // Pre: all instances to be inserted must satisfy
93 // !hasPackage() && hasVersion() && hasInterface() && hasInstance()
94 bool insertInstances(const std::set<FqInstance>& fqInstances, std::string* error = nullptr);
89}; 95};
90 96
91} // namespace vintf 97} // namespace vintf
diff --git a/include/vintf/ManifestInstance.h b/include/vintf/ManifestInstance.h
index a2a89ef..61abbf1 100644
--- a/include/vintf/ManifestInstance.h
+++ b/include/vintf/ManifestInstance.h
@@ -29,6 +29,12 @@ namespace vintf {
29 29
30class ManifestInstance { 30class ManifestInstance {
31 public: 31 public:
32 ManifestInstance();
33 ManifestInstance(const ManifestInstance&);
34 ManifestInstance(ManifestInstance&&);
35 ManifestInstance& operator=(const ManifestInstance&);
36 ManifestInstance& operator=(ManifestInstance&&);
37
32 using VersionType = Version; 38 using VersionType = Version;
33 ManifestInstance(FqInstance&& fqInstance, TransportArch&& ta); 39 ManifestInstance(FqInstance&& fqInstance, TransportArch&& ta);
34 ManifestInstance(const FqInstance& fqInstance, const TransportArch& ta); 40 ManifestInstance(const FqInstance& fqInstance, const TransportArch& ta);
@@ -39,6 +45,15 @@ class ManifestInstance {
39 Transport transport() const; 45 Transport transport() const;
40 Arch arch() const; 46 Arch arch() const;
41 47
48 bool operator==(const ManifestInstance& other) const;
49 bool operator<(const ManifestInstance& other) const;
50
51 // Convenience methods.
52 // return package@version::interface/instance
53 const FqInstance& getFqInstance() const;
54 // return @version::interface/instance
55 FqInstance getFqInstanceNoPackage() const;
56
42 private: 57 private:
43 FqInstance mFqInstance; 58 FqInstance mFqInstance;
44 TransportArch mTransportArch; 59 TransportArch mTransportArch;
diff --git a/include/vintf/MatrixHal.h b/include/vintf/MatrixHal.h
index 29c44c7..6044792 100644
--- a/include/vintf/MatrixHal.h
+++ b/include/vintf/MatrixHal.h
@@ -47,14 +47,24 @@ struct MatrixHal {
47 std::map<std::string, HalInterface> interfaces; 47 std::map<std::string, HalInterface> interfaces;
48 48
49 inline const std::string& getName() const { return name; } 49 inline const std::string& getName() const { return name; }
50 inline bool hasInterface(const std::string& interface_name) const {
51 return interfaces.find(interface_name) != interfaces.end();
52 }
53 50
54 // Return true if "this" contains all interface/instance instances in "other". 51 // Return true if "this" contains all interface/instance instances in "other".
55 bool containsInstances(const MatrixHal& other) const; 52 bool containsInstances(const MatrixHal& other) const;
56 53
57 bool forEachInstance(const std::function<bool(const MatrixInstance&)>& func) const; 54 bool forEachInstance(const std::function<bool(const MatrixInstance&)>& func) const;
55
56 private:
57 friend struct HalManifest;
58 friend struct CompatibilityMatrix;
59 bool forEachInstance(const VersionRange& vr,
60 const std::function<bool(const MatrixInstance&)>& func) const;
61 bool isCompatible(const std::set<FqInstance>& providedInstances,
62 const std::set<Version>& providedVersions) const;
63 bool isCompatible(const VersionRange& vr, const std::set<FqInstance>& providedInstances,
64 const std::set<Version>& providedVersions) const;
65
66 void setOptional(bool o);
67 void insertVersionRanges(const MatrixHal& other);
58}; 68};
59 69
60} // namespace vintf 70} // namespace vintf
diff --git a/include/vintf/MatrixInstance.h b/include/vintf/MatrixInstance.h
index bbd57dc..c3d2a0b 100644
--- a/include/vintf/MatrixInstance.h
+++ b/include/vintf/MatrixInstance.h
@@ -28,6 +28,12 @@ namespace vintf {
28 28
29class MatrixInstance { 29class MatrixInstance {
30 public: 30 public:
31 MatrixInstance();
32 MatrixInstance(const MatrixInstance&);
33 MatrixInstance(MatrixInstance&&);
34 MatrixInstance& operator=(const MatrixInstance&);
35 MatrixInstance& operator=(MatrixInstance&&);
36
31 using VersionType = VersionRange; 37 using VersionType = VersionRange;
32 // fqInstance.version is ignored. Version range is provided separately. 38 // fqInstance.version is ignored. Version range is provided separately.
33 MatrixInstance(FqInstance&& fqInstance, VersionRange&& range, bool optional); 39 MatrixInstance(FqInstance&& fqInstance, VersionRange&& range, bool optional);
@@ -38,6 +44,8 @@ class MatrixInstance {
38 const std::string& instance() const; 44 const std::string& instance() const;
39 bool optional() const; 45 bool optional() const;
40 46
47 bool isSatisfiedBy(const FqInstance& provided) const;
48
41 private: 49 private:
42 FqInstance mFqInstance; 50 FqInstance mFqInstance;
43 VersionRange mRange; 51 VersionRange mRange;
diff --git a/include/vintf/TransportArch.h b/include/vintf/TransportArch.h
index f09b6f0..b1d9352 100644
--- a/include/vintf/TransportArch.h
+++ b/include/vintf/TransportArch.h
@@ -28,7 +28,16 @@ struct TransportArch {
28 Transport transport = Transport::EMPTY; 28 Transport transport = Transport::EMPTY;
29 Arch arch = Arch::ARCH_EMPTY; 29 Arch arch = Arch::ARCH_EMPTY;
30 30
31private: 31 inline bool operator==(const TransportArch& other) const {
32 return transport == other.transport && arch == other.arch;
33 }
34 inline bool operator<(const TransportArch& other) const {
35 if (transport < other.transport) return true;
36 if (transport > other.transport) return false;
37 return arch < other.arch;
38 }
39
40 private:
32 friend struct TransportArchConverter; 41 friend struct TransportArchConverter;
33 friend struct ManifestHalConverter; 42 friend struct ManifestHalConverter;
34 friend struct ManifestHal; 43 friend struct ManifestHal;
diff --git a/include/vintf/VersionRange.h b/include/vintf/VersionRange.h
index b8f1465..6c5690b 100644
--- a/include/vintf/VersionRange.h
+++ b/include/vintf/VersionRange.h
@@ -58,6 +58,15 @@ struct VersionRange {
58 return majorVer == ver.majorVer && minMinor <= ver.minorVer; 58 return majorVer == ver.majorVer && minMinor <= ver.minorVer;
59 } 59 }
60 60
61 // If a.overlaps(b) then b.overlaps(a).
62 // 1.2-4 and 2.2-4: false
63 // 1.2-4 and 1.4-5: true
64 // 1.2-4 and 1.0-1: false
65 inline bool overlaps(const VersionRange& other) const {
66 return majorVer == other.majorVer && minMinor <= other.maxMinor &&
67 other.minMinor <= maxMinor;
68 }
69
61 size_t majorVer; 70 size_t majorVer;
62 size_t minMinor; 71 size_t minMinor;
63 size_t maxMinor; 72 size_t maxMinor;
diff --git a/include/vintf/parse_string.h b/include/vintf/parse_string.h
index 8820639..1094795 100644
--- a/include/vintf/parse_string.h
+++ b/include/vintf/parse_string.h
@@ -51,6 +51,7 @@ std::ostream &operator<<(std::ostream &os, const TransportArch &ta);
51std::ostream &operator<<(std::ostream &os, const ManifestHal &hal); 51std::ostream &operator<<(std::ostream &os, const ManifestHal &hal);
52std::ostream &operator<<(std::ostream &os, const MatrixHal &req); 52std::ostream &operator<<(std::ostream &os, const MatrixHal &req);
53std::ostream &operator<<(std::ostream &os, const KernelConfigTypedValue &kcv); 53std::ostream &operator<<(std::ostream &os, const KernelConfigTypedValue &kcv);
54std::ostream& operator<<(std::ostream& os, const FqInstance& fqInstance);
54 55
55template <typename T> 56template <typename T>
56std::string to_string(const T &obj) { 57std::string to_string(const T &obj) {
@@ -83,6 +84,7 @@ bool parse(const std::string &s, TransportArch *ta);
83// if return true, hal->isValid() must be true. 84// if return true, hal->isValid() must be true.
84bool parse(const std::string &s, ManifestHal *hal); 85bool parse(const std::string &s, ManifestHal *hal);
85bool parse(const std::string &s, MatrixHal *req); 86bool parse(const std::string &s, MatrixHal *req);
87bool parse(const std::string& s, FqInstance* fqInstance);
86 88
87bool parseKernelConfigInt(const std::string &s, int64_t *i); 89bool parseKernelConfigInt(const std::string &s, int64_t *i);
88bool parseKernelConfigInt(const std::string &s, uint64_t *i); 90bool parseKernelConfigInt(const std::string &s, uint64_t *i);
diff --git a/include/vintf/parse_xml.h b/include/vintf/parse_xml.h
index 59db3bf..578e15b 100644
--- a/include/vintf/parse_xml.h
+++ b/include/vintf/parse_xml.h
@@ -31,10 +31,14 @@ enum SerializeFlag : uint32_t {
31 NO_KERNEL = 1 << 4, 31 NO_KERNEL = 1 << 4,
32 NO_XMLFILES = 1 << 5, 32 NO_XMLFILES = 1 << 5,
33 NO_SSDK = 1 << 6, 33 NO_SSDK = 1 << 6,
34 NO_FQNAME = 1 << 7,
34 35
35 EVERYTHING = 0, 36 EVERYTHING = 0,
36 HALS_ONLY = ~NO_HALS, 37 HALS_ONLY = ~(NO_HALS | NO_FQNAME), // <hal> with <fqname>
37 XMLFILES_ONLY = ~NO_XMLFILES, 38 XMLFILES_ONLY = ~NO_XMLFILES,
39 SEPOLICY_ONLY = ~NO_SEPOLICY,
40 VNDK_ONLY = ~NO_VNDK,
41 HALS_NO_FQNAME = ~NO_HALS, // <hal> without <fqname>
38}; 42};
39using SerializeFlags = uint32_t; 43using SerializeFlags = uint32_t;
40 44
diff --git a/parse_string.cpp b/parse_string.cpp
index 2aa3c1b..0aff5ea 100644
--- a/parse_string.cpp
+++ b/parse_string.cpp
@@ -395,16 +395,22 @@ std::ostream &operator<<(std::ostream &os, const MatrixHal &req) {
395 << (req.optional ? kOptional : kRequired); 395 << (req.optional ? kOptional : kRequired);
396} 396}
397 397
398static std::string expandInstances(const MatrixHal& req, const VersionRange& vr) { 398static std::string expandInstances(const MatrixHal& req, const VersionRange& vr, bool brace) {
399 std::string s; 399 std::string s;
400 bool first = true; 400 size_t count = 0;
401 for (const auto& interface : iterateValues(req.interfaces)) { 401 for (const auto& interface : iterateValues(req.interfaces)) {
402 for (const auto& instance : interface.instances) { 402 for (const auto& instance : interface.instances) {
403 if (!first) s += " AND "; 403 if (count > 0) s += " AND ";
404 s += toFQNameString(vr, interface.name, instance); 404 s += toFQNameString(vr, interface.name, instance);
405 first = false; 405 count++;
406 } 406 }
407 } 407 }
408 if (count == 0) {
409 s += "@" + to_string(vr);
410 }
411 if (count >= 2 && brace) {
412 s = "(" + s + ")";
413 }
408 return s; 414 return s;
409} 415}
410 416
@@ -414,14 +420,14 @@ std::vector<std::string> expandInstances(const MatrixHal& req) {
414 } 420 }
415 if (req.versionRanges.size() == 1 && req.interfaces.size() == 1 && 421 if (req.versionRanges.size() == 1 && req.interfaces.size() == 1 &&
416 req.interfaces.begin()->second.instances.size() == 1) { 422 req.interfaces.begin()->second.instances.size() == 1) {
417 return {expandInstances(req, req.versionRanges.front())}; 423 return {expandInstances(req, req.versionRanges.front(), false /* brace */)};
418 } 424 }
419 std::vector<std::string> ss; 425 std::vector<std::string> ss;
420 for (const auto& vr : req.versionRanges) { 426 for (const auto& vr : req.versionRanges) {
421 if (!ss.empty()) { 427 if (!ss.empty()) {
422 ss.back() += " OR"; 428 ss.back() += " OR";
423 } 429 }
424 ss.push_back("(" + expandInstances(req, vr) + ")"); 430 ss.push_back(expandInstances(req, vr, true /* brace */));
425 } 431 }
426 return ss; 432 return ss;
427} 433}
@@ -505,5 +511,13 @@ std::string toFQNameString(const VersionRange& range, const std::string& interfa
505 return toFQNameString("", range, interface, instance); 511 return toFQNameString("", range, interface, instance);
506} 512}
507 513
514std::ostream& operator<<(std::ostream& os, const FqInstance& fqInstance) {
515 return os << fqInstance.string();
516}
517
518bool parse(const std::string& s, FqInstance* fqInstance) {
519 return fqInstance->setTo(s);
520}
521
508} // namespace vintf 522} // namespace vintf
509} // namespace android 523} // namespace android
diff --git a/parse_xml.cpp b/parse_xml.cpp
index bf8889f..38a09b4 100644
--- a/parse_xml.cpp
+++ b/parse_xml.cpp
@@ -230,11 +230,12 @@ struct XmlNodeConverter : public XmlConverter<Object> {
230 } 230 }
231 } 231 }
232 232
233 template<typename T, typename Array> 233 template <typename T, typename Array>
234 inline void appendChildren(NodeType *parent, const XmlNodeConverter<T> &conv, 234 inline void appendChildren(NodeType* parent, const XmlNodeConverter<T>& conv,
235 const Array &array, DocType *d) const { 235 const Array& array, DocType* d,
236 SerializeFlags flags = SerializeFlag::EVERYTHING) const {
236 for (const T &t : array) { 237 for (const T &t : array) {
237 appendChild(parent, conv(t, d)); 238 appendChild(parent, conv.serialize(t, d, flags));
238 } 239 }
239 } 240 }
240 241
@@ -600,9 +601,15 @@ struct MatrixKernelConverter : public XmlNodeConverter<MatrixKernel> {
600 601
601MatrixKernelConverter matrixKernelConverter{}; 602MatrixKernelConverter matrixKernelConverter{};
602 603
604XmlTextConverter<FqInstance> fqInstanceConverter{"fqname"};
605
603struct ManifestHalConverter : public XmlNodeConverter<ManifestHal> { 606struct ManifestHalConverter : public XmlNodeConverter<ManifestHal> {
604 std::string elementName() const override { return "hal"; } 607 std::string elementName() const override { return "hal"; }
605 void mutateNode(const ManifestHal &hal, NodeType *root, DocType *d) const override { 608 void mutateNode(const ManifestHal& m, NodeType* root, DocType* d) const override {
609 mutateNode(m, root, d, SerializeFlag::EVERYTHING);
610 }
611 void mutateNode(const ManifestHal& hal, NodeType* root, DocType* d,
612 SerializeFlags flags) const override {
606 appendAttr(root, "format", hal.format); 613 appendAttr(root, "format", hal.format);
607 appendTextElement(root, "name", hal.name, d); 614 appendTextElement(root, "name", hal.name, d);
608 appendChild(root, transportArchConverter(hal.transportArch, d)); 615 appendChild(root, transportArchConverter(hal.transportArch, d));
@@ -611,6 +618,15 @@ struct ManifestHalConverter : public XmlNodeConverter<ManifestHal> {
611 if (hal.isOverride()) { 618 if (hal.isOverride()) {
612 appendAttr(root, "override", hal.isOverride()); 619 appendAttr(root, "override", hal.isOverride());
613 } 620 }
621
622 if (!(flags & SerializeFlag::NO_FQNAME)) {
623 std::set<FqInstance> fqInstances;
624 hal.forEachInstance([&fqInstances](const auto& manifestInstance) {
625 fqInstances.emplace(manifestInstance.getFqInstanceNoPackage());
626 return true;
627 });
628 appendChildren(root, fqInstanceConverter, fqInstances, d);
629 }
614 } 630 }
615 bool buildObject(ManifestHal* object, NodeType* root, std::string* error) const override { 631 bool buildObject(ManifestHal* object, NodeType* root, std::string* error) const override {
616 std::vector<HalInterface> interfaces; 632 std::vector<HalInterface> interfaces;
@@ -666,6 +682,15 @@ struct ManifestHalConverter : public XmlNodeConverter<ManifestHal> {
666 return false; 682 return false;
667 } 683 }
668#endif 684#endif
685
686 std::set<FqInstance> fqInstances;
687 if (!parseChildren(root, fqInstanceConverter, &fqInstances, error)) {
688 return false;
689 }
690 if (!object->insertInstances(fqInstances, error)) {
691 return false;
692 }
693
669 return true; 694 return true;
670 } 695 }
671 696
@@ -808,7 +833,7 @@ struct HalManifestConverter : public XmlNodeConverter<HalManifest> {
808 appendAttr(root, "type", m.mType); 833 appendAttr(root, "type", m.mType);
809 834
810 if (!(flags & SerializeFlag::NO_HALS)) { 835 if (!(flags & SerializeFlag::NO_HALS)) {
811 appendChildren(root, manifestHalConverter, m.getHals(), d); 836 appendChildren(root, manifestHalConverter, m.getHals(), d, flags);
812 } 837 }
813 if (m.mType == SchemaType::DEVICE) { 838 if (m.mType == SchemaType::DEVICE) {
814 if (!(flags & SerializeFlag::NO_SEPOLICY)) { 839 if (!(flags & SerializeFlag::NO_SEPOLICY)) {
diff --git a/test/AssembleVintfTest.cpp b/test/AssembleVintfTest.cpp
index 4410a5c..e01a15e 100644
--- a/test/AssembleVintfTest.cpp
+++ b/test/AssembleVintfTest.cpp
@@ -232,13 +232,6 @@ TEST_F(AssembleVintfTest, FrameworkMatrix) {
232 " <hal format=\"hidl\" optional=\"true\">\n" 232 " <hal format=\"hidl\" optional=\"true\">\n"
233 " <name>android.hardware.foo</name>\n" 233 " <name>android.hardware.foo</name>\n"
234 " <version>1.0-1</version>\n" 234 " <version>1.0-1</version>\n"
235 " <interface>\n"
236 " <name>IFoo</name>\n"
237 " <instance>default</instance>\n"
238 " </interface>\n"
239 " </hal>\n"
240 " <hal format=\"hidl\" optional=\"true\">\n"
241 " <name>android.hardware.foo</name>\n"
242 " <version>2.0</version>\n" 235 " <version>2.0</version>\n"
243 " <interface>\n" 236 " <interface>\n"
244 " <name>IFoo</name>\n" 237 " <name>IFoo</name>\n"
@@ -256,13 +249,6 @@ TEST_F(AssembleVintfTest, FrameworkMatrix) {
256 " <hal format=\"hidl\" optional=\"true\">\n" 249 " <hal format=\"hidl\" optional=\"true\">\n"
257 " <name>android.hardware.foo</name>\n" 250 " <name>android.hardware.foo</name>\n"
258 " <version>1.0-1</version>\n" 251 " <version>1.0-1</version>\n"
259 " <interface>\n"
260 " <name>IFoo</name>\n"
261 " <instance>default</instance>\n"
262 " </interface>\n"
263 " </hal>\n"
264 " <hal format=\"hidl\" optional=\"true\">\n"
265 " <name>android.hardware.foo</name>\n"
266 " <version>2.0</version>\n" 252 " <version>2.0</version>\n"
267 " <interface>\n" 253 " <interface>\n"
268 " <name>IFoo</name>\n" 254 " <name>IFoo</name>\n"
diff --git a/test/LibVintfTest.cpp b/test/LibVintfTest.cpp
index f0f0423..fc7ebc9 100644
--- a/test/LibVintfTest.cpp
+++ b/test/LibVintfTest.cpp
@@ -251,7 +251,8 @@ TEST_F(LibVintfTest, FutureManifestCompatible) {
251 251
252TEST_F(LibVintfTest, HalManifestConverter) { 252TEST_F(LibVintfTest, HalManifestConverter) {
253 HalManifest vm = testDeviceManifest(); 253 HalManifest vm = testDeviceManifest();
254 std::string xml = gHalManifestConverter(vm); 254 std::string xml =
255 gHalManifestConverter(vm, SerializeFlag::HALS_NO_FQNAME & SerializeFlag::SEPOLICY_ONLY);
255 EXPECT_EQ(xml, 256 EXPECT_EQ(xml,
256 "<manifest version=\"1.0\" type=\"device\">\n" 257 "<manifest version=\"1.0\" type=\"device\">\n"
257 " <hal format=\"hidl\">\n" 258 " <hal format=\"hidl\">\n"
@@ -288,7 +289,8 @@ TEST_F(LibVintfTest, HalManifestConverter) {
288 289
289TEST_F(LibVintfTest, HalManifestConverterFramework) { 290TEST_F(LibVintfTest, HalManifestConverterFramework) {
290 HalManifest vm = testFrameworkManfiest(); 291 HalManifest vm = testFrameworkManfiest();
291 std::string xml = gHalManifestConverter(vm); 292 std::string xml =
293 gHalManifestConverter(vm, SerializeFlag::HALS_NO_FQNAME & SerializeFlag::VNDK_ONLY);
292 EXPECT_EQ(xml, 294 EXPECT_EQ(xml,
293 "<manifest version=\"1.0\" type=\"framework\">\n" 295 "<manifest version=\"1.0\" type=\"framework\">\n"
294 " <hal format=\"hidl\">\n" 296 " <hal format=\"hidl\">\n"
@@ -1042,7 +1044,7 @@ TEST_F(LibVintfTest, HalCompat) {
1042 HalManifest manifest; 1044 HalManifest manifest;
1043 EXPECT_TRUE(gHalManifestConverter(&manifest, manifestXml)); 1045 EXPECT_TRUE(gHalManifestConverter(&manifest, manifestXml));
1044 EXPECT_FALSE(manifest.checkCompatibility(matrix, &error)) 1046 EXPECT_FALSE(manifest.checkCompatibility(matrix, &error))
1045 << "should not be compatible because IFoo/default is missing"; 1047 << "should not be compatible because IFoo/specific is missing";
1046 } 1048 }
1047 1049
1048 { 1050 {
@@ -1275,7 +1277,9 @@ TEST_F(LibVintfTest, Compat) {
1275 1277
1276TEST_F(LibVintfTest, HalManifestConverterXmlFile) { 1278TEST_F(LibVintfTest, HalManifestConverterXmlFile) {
1277 HalManifest vm = testDeviceManifestWithXmlFile(); 1279 HalManifest vm = testDeviceManifestWithXmlFile();
1278 std::string xml = gHalManifestConverter(vm); 1280 std::string xml =
1281 gHalManifestConverter(vm, SerializeFlag::HALS_NO_FQNAME & SerializeFlag::SEPOLICY_ONLY &
1282 SerializeFlag::XMLFILES_ONLY);
1279 EXPECT_EQ(xml, 1283 EXPECT_EQ(xml,
1280 "<manifest version=\"1.0\" type=\"device\">\n" 1284 "<manifest version=\"1.0\" type=\"device\">\n"
1281 " <hal format=\"hidl\">\n" 1285 " <hal format=\"hidl\">\n"
@@ -2154,7 +2158,7 @@ TEST_F(LibVintfTest, AddOptionalHalMinorVersion) {
2154 "<compatibility-matrix version=\"1.0\" type=\"framework\" level=\"1\">\n" 2158 "<compatibility-matrix version=\"1.0\" type=\"framework\" level=\"1\">\n"
2155 " <hal format=\"hidl\" optional=\"false\">\n" 2159 " <hal format=\"hidl\" optional=\"false\">\n"
2156 " <name>android.hardware.foo</name>\n" 2160 " <name>android.hardware.foo</name>\n"
2157 " <version>1.2-4</version>\n" 2161 " <version>1.0-4</version>\n"
2158 " <interface>\n" 2162 " <interface>\n"
2159 " <name>IFoo</name>\n" 2163 " <name>IFoo</name>\n"
2160 " <instance>default</instance>\n" 2164 " <instance>default</instance>\n"
@@ -2205,19 +2209,69 @@ TEST_F(LibVintfTest, AddOptionalHalMajorVersion) {
2205 " <hal format=\"hidl\" optional=\"false\">\n" 2209 " <hal format=\"hidl\" optional=\"false\">\n"
2206 " <name>android.hardware.foo</name>\n" 2210 " <name>android.hardware.foo</name>\n"
2207 " <version>1.2-3</version>\n" 2211 " <version>1.2-3</version>\n"
2212 " <version>2.0-4</version>\n"
2208 " <interface>\n" 2213 " <interface>\n"
2209 " <name>IFoo</name>\n" 2214 " <name>IFoo</name>\n"
2210 " <instance>default</instance>\n" 2215 " <instance>default</instance>\n"
2211 " </interface>\n" 2216 " </interface>\n"
2212 " </hal>\n" 2217 " </hal>\n"
2213 " <hal format=\"hidl\" optional=\"true\">\n" 2218 "</compatibility-matrix>\n");
2219}
2220
2221TEST_F(LibVintfTest, AddOptionalHalMinorVersionDiffInstance) {
2222 CompatibilityMatrix cm1;
2223 CompatibilityMatrix cm2;
2224 std::string error;
2225 std::string xml;
2226
2227 xml =
2228 "<compatibility-matrix version=\"1.0\" type=\"framework\" level=\"1\">\n"
2229 " <hal format=\"hidl\" optional=\"false\">\n"
2230 " <name>android.hardware.foo</name>\n"
2231 " <version>1.0-1</version>\n"
2232 " <interface>\n"
2233 " <name>IFoo</name>\n"
2234 " <instance>default</instance>\n"
2235 " </interface>\n"
2236 " </hal>\n"
2237 "</compatibility-matrix>\n";
2238 EXPECT_TRUE(gCompatibilityMatrixConverter(&cm1, xml))
2239 << gCompatibilityMatrixConverter.lastError();
2240
2241 xml =
2242 "<compatibility-matrix version=\"1.0\" type=\"framework\" level=\"2\">\n"
2243 " <hal format=\"hidl\" optional=\"false\">\n"
2244 " <name>android.hardware.foo</name>\n"
2245 " <version>1.1-2</version>\n"
2246 " <interface>\n"
2247 " <name>IFoo</name>\n"
2248 " <instance>custom</instance>\n"
2249 " </interface>\n"
2250 " </hal>\n"
2251 "</compatibility-matrix>\n";
2252 EXPECT_TRUE(gCompatibilityMatrixConverter(&cm2, xml))
2253 << gCompatibilityMatrixConverter.lastError();
2254
2255 EXPECT_TRUE(addAllHalsAsOptional(&cm1, &cm2, &error)) << error;
2256 xml = gCompatibilityMatrixConverter(cm1, SerializeFlag::HALS_ONLY);
2257 EXPECT_EQ(xml,
2258 "<compatibility-matrix version=\"1.0\" type=\"framework\" level=\"1\">\n"
2259 " <hal format=\"hidl\" optional=\"false\">\n"
2214 " <name>android.hardware.foo</name>\n" 2260 " <name>android.hardware.foo</name>\n"
2215 " <version>2.0-4</version>\n" 2261 " <version>1.0-1</version>\n"
2216 " <interface>\n" 2262 " <interface>\n"
2217 " <name>IFoo</name>\n" 2263 " <name>IFoo</name>\n"
2218 " <instance>default</instance>\n" 2264 " <instance>default</instance>\n"
2219 " </interface>\n" 2265 " </interface>\n"
2220 " </hal>\n" 2266 " </hal>\n"
2267 " <hal format=\"hidl\" optional=\"true\">\n"
2268 " <name>android.hardware.foo</name>\n"
2269 " <version>1.1-2</version>\n"
2270 " <interface>\n"
2271 " <name>IFoo</name>\n"
2272 " <instance>custom</instance>\n"
2273 " </interface>\n"
2274 " </hal>\n"
2221 "</compatibility-matrix>\n"); 2275 "</compatibility-matrix>\n");
2222} 2276}
2223 2277
@@ -2435,7 +2489,7 @@ TEST_F(LibVintfTest, ManifestAddOverrideHalSimple) {
2435 EXPECT_TRUE(gHalManifestConverter(&newManifest, xml)) << gHalManifestConverter.lastError(); 2489 EXPECT_TRUE(gHalManifestConverter(&newManifest, xml)) << gHalManifestConverter.lastError();
2436 2490
2437 manifest.addAllHals(&newManifest); 2491 manifest.addAllHals(&newManifest);
2438 EXPECT_EQ(xml, gHalManifestConverter(manifest, SerializeFlag::HALS_ONLY)); 2492 EXPECT_EQ(xml, gHalManifestConverter(manifest, SerializeFlag::HALS_NO_FQNAME));
2439} 2493}
2440 2494
2441TEST_F(LibVintfTest, ManifestAddOverrideHalSimpleOverride) { 2495TEST_F(LibVintfTest, ManifestAddOverrideHalSimpleOverride) {
@@ -2466,7 +2520,7 @@ TEST_F(LibVintfTest, ManifestAddOverrideHalSimpleOverride) {
2466 EXPECT_TRUE(gHalManifestConverter(&newManifest, xml)) << gHalManifestConverter.lastError(); 2520 EXPECT_TRUE(gHalManifestConverter(&newManifest, xml)) << gHalManifestConverter.lastError();
2467 2521
2468 manifest.addAllHals(&newManifest); 2522 manifest.addAllHals(&newManifest);
2469 EXPECT_EQ(xml, gHalManifestConverter(manifest, SerializeFlag::HALS_ONLY)); 2523 EXPECT_EQ(xml, gHalManifestConverter(manifest, SerializeFlag::HALS_NO_FQNAME));
2470} 2524}
2471 2525
2472// Existing major versions should be removed. 2526// Existing major versions should be removed.
@@ -2536,7 +2590,7 @@ TEST_F(LibVintfTest, ManifestAddOverrideHalMultiVersion) {
2536 " </interface>\n" 2590 " </interface>\n"
2537 " </hal>\n" 2591 " </hal>\n"
2538 "</manifest>\n", 2592 "</manifest>\n",
2539 gHalManifestConverter(manifest, SerializeFlag::HALS_ONLY)); 2593 gHalManifestConverter(manifest, SerializeFlag::HALS_NO_FQNAME));
2540} 2594}
2541 2595
2542TEST_F(LibVintfTest, ManifestAddOverrideHalMultiVersion2) { 2596TEST_F(LibVintfTest, ManifestAddOverrideHalMultiVersion2) {
@@ -2573,7 +2627,7 @@ TEST_F(LibVintfTest, ManifestAddOverrideHalMultiVersion2) {
2573 EXPECT_TRUE(gHalManifestConverter(&newManifest, xml)) << gHalManifestConverter.lastError(); 2627 EXPECT_TRUE(gHalManifestConverter(&newManifest, xml)) << gHalManifestConverter.lastError();
2574 2628
2575 manifest.addAllHals(&newManifest); 2629 manifest.addAllHals(&newManifest);
2576 EXPECT_EQ(xml, gHalManifestConverter(manifest, SerializeFlag::HALS_ONLY)); 2630 EXPECT_EQ(xml, gHalManifestConverter(manifest, SerializeFlag::HALS_NO_FQNAME));
2577} 2631}
2578 2632
2579// if no <versions>, remove all existing <hal> with given <name>. 2633// if no <versions>, remove all existing <hal> with given <name>.
@@ -2836,6 +2890,203 @@ TEST_F(LibVintfTest, MatrixDetailErrorMsg) {
2836 } 2890 }
2837} 2891}
2838 2892
2893TEST_F(LibVintfTest, DisabledHal) {
2894 std::string error;
2895 std::string xml;
2896 HalManifest manifest;
2897 xml =
2898 "<manifest version=\"1.0\" type=\"framework\">\n"
2899 " <hal format=\"hidl\" override=\"true\">\n"
2900 " <transport>hwbinder</transport>\n"
2901 " <name>android.hardware.foo</name>\n"
2902 " <transport>hwbinder</transport>\n"
2903 " </hal>\n"
2904 " <hal format=\"hidl\" override=\"true\">\n"
2905 " <name>android.hardware.bar</name>\n"
2906 " <transport>hwbinder</transport>\n"
2907 " <fqname>@1.1::IFoo/custom</fqname>\n"
2908 " </hal>\n"
2909 " <hal format=\"hidl\">\n"
2910 " <name>android.hardware.baz</name>\n"
2911 " <transport>hwbinder</transport>\n"
2912 " </hal>\n"
2913 "</manifest>\n";
2914 ASSERT_TRUE(gHalManifestConverter(&manifest, xml, &error)) << error;
2915
2916 auto foo = manifest.getHals("android.hardware.foo");
2917 ASSERT_EQ(1u, foo.size());
2918 EXPECT_TRUE(foo.front()->isDisabledHal());
2919 auto bar = manifest.getHals("android.hardware.bar");
2920 ASSERT_EQ(1u, bar.size());
2921 EXPECT_FALSE(bar.front()->isDisabledHal());
2922 auto baz = manifest.getHals("android.hardware.baz");
2923 ASSERT_EQ(1u, baz.size());
2924 EXPECT_FALSE(baz.front()->isDisabledHal());
2925}
2926
2927TEST_F(LibVintfTest, FqNameValid) {
2928 std::string error;
2929 std::string xml;
2930
2931 CompatibilityMatrix cm;
2932 xml =
2933 "<compatibility-matrix version=\"1.0\" type=\"device\">\n"
2934 " <hal format=\"hidl\" optional=\"false\">\n"
2935 " <name>android.hardware.foo</name>\n"
2936 " <version>1.0</version>\n"
2937 " <interface>\n"
2938 " <name>IFoo</name>\n"
2939 " <instance>default</instance>\n"
2940 " </interface>\n"
2941 " </hal>\n"
2942 " <hal format=\"hidl\" optional=\"false\">\n"
2943 " <name>android.hardware.foo</name>\n"
2944 " <version>1.1</version>\n"
2945 " <interface>\n"
2946 " <name>IFoo</name>\n"
2947 " <instance>custom</instance>\n"
2948 " </interface>\n"
2949 " </hal>\n"
2950 "</compatibility-matrix>\n";
2951 EXPECT_TRUE(gCompatibilityMatrixConverter(&cm, xml, &error)) << error;
2952
2953 {
2954 HalManifest manifest;
2955 xml =
2956 "<manifest version=\"1.0\" type=\"framework\">\n"
2957 " <hal format=\"hidl\">\n"
2958 " <name>android.hardware.foo</name>\n"
2959 " <transport>hwbinder</transport>\n"
2960 " <version>1.0</version>\n"
2961 " <interface>\n"
2962 " <name>IFoo</name>\n"
2963 " <instance>default</instance>\n"
2964 " <instance>custom</instance>\n"
2965 " </interface>\n"
2966 " <fqname>@1.1::IFoo/custom</fqname>\n"
2967 " </hal>\n"
2968 "</manifest>\n";
2969 ASSERT_TRUE(gHalManifestConverter(&manifest, xml, &error)) << error;
2970 EXPECT_TRUE(manifest.checkCompatibility(cm, &error)) << error;
2971 }
2972
2973 {
2974 HalManifest manifest;
2975 xml =
2976 "<manifest version=\"1.0\" type=\"framework\">\n"
2977 " <hal format=\"hidl\">\n"
2978 " <name>android.hardware.foo</name>\n"
2979 " <transport>hwbinder</transport>\n"
2980 " <fqname>@1.0::IFoo/default</fqname>\n"
2981 " <fqname>@1.1::IFoo/custom</fqname>\n"
2982 " </hal>\n"
2983 "</manifest>\n";
2984 ASSERT_TRUE(gHalManifestConverter(&manifest, xml, &error)) << error;
2985 EXPECT_TRUE(manifest.checkCompatibility(cm, &error)) << error;
2986 }
2987
2988 {
2989 HalManifest manifest;
2990 xml =
2991 "<manifest version=\"1.0\" type=\"framework\">\n"
2992 " <hal format=\"hidl\">\n"
2993 " <name>android.hardware.foo</name>\n"
2994 " <transport>hwbinder</transport>\n"
2995 " <version>1.0</version>\n"
2996 " <interface>\n"
2997 " <name>IFoo</name>\n"
2998 " <instance>default</instance>\n"
2999 " <instance>custom</instance>\n"
3000 " </interface>\n"
3001 " </hal>\n"
3002 "</manifest>\n";
3003 ASSERT_TRUE(gHalManifestConverter(&manifest, xml, &error)) << error;
3004 EXPECT_FALSE(manifest.checkCompatibility(cm, &error));
3005 EXPECT_IN(
3006 "android.hardware.foo:\n"
3007 " required: @1.1::IFoo/custom\n"
3008 " provided: \n"
3009 " @1.0::IFoo/custom\n"
3010 " @1.0::IFoo/default",
3011 error);
3012 }
3013
3014 {
3015 HalManifest manifest;
3016 xml =
3017 "<manifest version=\"1.0\" type=\"framework\">\n"
3018 " <hal format=\"hidl\">\n"
3019 " <name>android.hardware.foo</name>\n"
3020 " <transport>hwbinder</transport>\n"
3021 " <fqname>@1.0::IFoo/default</fqname>\n"
3022 " <fqname>@1.0::IFoo/custom</fqname>\n"
3023 " </hal>\n"
3024 "</manifest>\n";
3025 ASSERT_TRUE(gHalManifestConverter(&manifest, xml, &error)) << error;
3026 EXPECT_IN(
3027 "android.hardware.foo:\n"
3028 " required: @1.1::IFoo/custom\n"
3029 " provided: \n"
3030 " @1.0::IFoo/custom\n"
3031 " @1.0::IFoo/default",
3032 error);
3033 }
3034}
3035
3036TEST_F(LibVintfTest, FqNameInvalid) {
3037 std::string error;
3038 std::string xml;
3039 ManifestHal hal;
3040 xml =
3041 "<hal format=\"hidl\">\n"
3042 " <name>android.hardware.foo</name>\n"
3043 " <transport>hwbinder</transport>\n"
3044 " <fqname>@1.1::IFoo/custom</fqname>\n"
3045 "</hal>\n";
3046 EXPECT_TRUE(gManifestHalConverter(&hal, xml, &error)) << error;
3047 xml =
3048 "<hal format=\"hidl\">\n"
3049 " <name>android.hardware.foo</name>\n"
3050 " <transport>hwbinder</transport>\n"
3051 " <fqname>1.1::IFoo/custom</fqname>\n"
3052 "</hal>\n";
3053 ASSERT_FALSE(gManifestHalConverter(&hal, xml, &error));
3054 EXPECT_IN("Could not parse text \"1.1::IFoo/custom\" in element <fqname>", error);
3055 xml =
3056 "<hal format=\"hidl\">\n"
3057 " <name>android.hardware.foo</name>\n"
3058 " <transport>hwbinder</transport>\n"
3059 " <fqname>android.hardware.foo@1.1::IFoo/custom</fqname>\n"
3060 "</hal>\n";
3061 ASSERT_FALSE(gManifestHalConverter(&hal, xml, &error));
3062 EXPECT_IN("Should not specify package", error);
3063 xml =
3064 "<hal format=\"hidl\">\n"
3065 " <name>android.hardware.foo</name>\n"
3066 " <transport>hwbinder</transport>\n"
3067 " <fqname>IFoo/custom</fqname>\n"
3068 "</hal>\n";
3069 ASSERT_FALSE(gManifestHalConverter(&hal, xml, &error));
3070 EXPECT_IN("Should specify version", error);
3071 xml =
3072 "<hal format=\"hidl\">\n"
3073 " <name>android.hardware.foo</name>\n"
3074 " <transport>hwbinder</transport>\n"
3075 " <fqname>@1.0::IFoo</fqname>\n"
3076 "</hal>\n";
3077 ASSERT_FALSE(gManifestHalConverter(&hal, xml, &error));
3078 EXPECT_IN("Should specify instance", error);
3079 xml =
3080 "<hal format=\"hidl\">\n"
3081 " <name>n07 4 v4l1d 1n73rf4c3</name>\n"
3082 " <transport>hwbinder</transport>\n"
3083 " <fqname>@1.0::IFoo/custom</fqname>\n"
3084 "</hal>\n";
3085 ASSERT_FALSE(gManifestHalConverter(&hal, xml, &error));
3086 EXPECT_IN("Cannot create FqInstance", error);
3087 EXPECT_IN("n07 4 v4l1d 1n73rf4c3", error);
3088}
3089
2839} // namespace vintf 3090} // namespace vintf
2840} // namespace android 3091} // namespace android
2841 3092