blob: d716a8d1bafaffb72d653096af2c7cf1104258ce [file] [log] [blame]
Yifan Hong676447a2016-11-15 12:57:23 -08001/*
2 * Copyright (C) 2017 The Android Open Source Project
3 *
4 * Licensed under the Apache License, Version 2.0 (the "License");
5 * you may not use this file except in compliance with the License.
6 * You may obtain a copy of the License at
7 *
8 * http://www.apache.org/licenses/LICENSE-2.0
9 *
10 * Unless required by applicable law or agreed to in writing, software
11 * distributed under the License is distributed on an "AS IS" BASIS,
12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 * See the License for the specific language governing permissions and
14 * limitations under the License.
15 */
16
17#include "MatrixHal.h"
18
Yifan Hong7967d7b2018-03-15 17:08:58 -070019#include <algorithm>
20
Yifan Hong2a90ffe2018-03-05 17:45:34 -080021#include "MapValueIterator.h"
22
Yifan Hong676447a2016-11-15 12:57:23 -080023namespace android {
24namespace vintf {
25
26bool MatrixHal::operator==(const MatrixHal &other) const {
27 if (format != other.format)
28 return false;
29 if (name != other.name)
30 return false;
31 if (versionRanges != other.versionRanges)
32 return false;
Yifan Hong43e2aae2017-05-17 18:36:08 -070033 if (interfaces != other.interfaces)
34 return false;
Yifan Hong676447a2016-11-15 12:57:23 -080035 // do not compare optional
36 return true;
37}
38
Zhuoyao Zhangc7e75bd2017-10-29 17:20:19 -070039bool MatrixHal::containsVersion(const Version& version) const {
40 for (VersionRange vRange : versionRanges) {
41 if (vRange.contains(version)) return true;
42 }
43 return false;
44}
45
46std::set<std::string> MatrixHal::getInstances(const std::string& interfaceName) const {
47 std::set<std::string> ret;
48 auto it = interfaces.find(interfaceName);
49 if (it != interfaces.end()) {
50 ret.insert(it->second.instances.begin(), it->second.instances.end());
51 }
52 return ret;
53}
54
Yifan Hongdbe9db32017-12-11 19:06:11 -080055bool MatrixHal::containsInstances(const MatrixHal& other) const {
56 for (const auto& pair : other.interfaces) {
57 const std::string& interfaceName = pair.first;
58 auto thisIt = interfaces.find(interfaceName);
59 if (thisIt == interfaces.end()) {
60 return false;
61 }
62
63 const std::set<std::string>& thisInstances = thisIt->second.instances;
64 const std::set<std::string>& otherInstances = pair.second.instances;
65 if (!std::includes(thisInstances.begin(), thisInstances.end(), otherInstances.begin(),
66 otherInstances.end())) {
67 return false;
68 }
69 }
70 return true;
71}
72
Yifan Hong2a90ffe2018-03-05 17:45:34 -080073bool MatrixHal::forEachInstance(const std::function<bool(const MatrixInstance&)>& func) const {
74 for (const auto& vr : versionRanges) {
Yifan Hong075b3632018-03-14 16:03:11 -070075 if (!forEachInstance(vr, func)) {
76 return false;
77 }
78 }
79 return true;
80}
81
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;
Yifan Hong2a90ffe2018-03-05 17:45:34 -080091 }
92 }
93 }
94 }
95 return true;
96}
97
Yifan Hong075b3632018-03-14 16:03:11 -070098bool 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
Yifan Hong7967d7b2018-03-15 17:08:58 -0700135void 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->maxMinor = std::max(existingVr->maxMinor, otherVr.maxMinor);
148 }
149 }
150}
151
Yifan Hong676447a2016-11-15 12:57:23 -0800152} // namespace vintf
153} // namespace android