blob: 8809b016c75e18b30ad69439409147421a317d55 [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"
Yifan Hong369472c2021-01-19 14:35:08 -080022#include "constants-private.h"
23#include "utils.h"
Yifan Hong2a90ffe2018-03-05 17:45:34 -080024
Yifan Hong676447a2016-11-15 12:57:23 -080025namespace android {
26namespace vintf {
27
Yifan Hong369472c2021-01-19 14:35:08 -080028using details::canConvertToFqInstance;
29
30bool MatrixHal::isValid(std::string* error) const {
31 bool success = true;
32
33 // Check legacy instances (i.e. <version> + <interface> + <instance>) can be
34 // converted into FqInstance because forEachInstance relies on FqInstance.
35 // Because <version> is a range, check both ends of the range.
36 for (const auto& vr : versionRanges) {
37 for (const auto& v : {vr.minVer(), vr.maxVer()}) {
38 for (const auto& intf : iterateValues(interfaces)) {
39 intf.forEachInstance([&](const auto& interface, const auto& instance,
40 bool /*isRegex*/) {
41 if (!canConvertToFqInstance(getName(), v, interface, instance, format, error)) {
42 success = false;
43 }
44 return true; // continue
45 });
46 }
47 }
48 }
49
50 return success;
51}
52
Yifan Hong676447a2016-11-15 12:57:23 -080053bool MatrixHal::operator==(const MatrixHal &other) const {
54 if (format != other.format)
55 return false;
56 if (name != other.name)
57 return false;
58 if (versionRanges != other.versionRanges)
59 return false;
Yifan Hong43e2aae2017-05-17 18:36:08 -070060 if (interfaces != other.interfaces)
61 return false;
Yifan Hong676447a2016-11-15 12:57:23 -080062 // do not compare optional
63 return true;
64}
65
Zhuoyao Zhangc7e75bd2017-10-29 17:20:19 -070066bool MatrixHal::containsVersion(const Version& version) const {
67 for (VersionRange vRange : versionRanges) {
68 if (vRange.contains(version)) return true;
69 }
70 return false;
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)) {
Yifan Hong7e9e04d2018-03-20 13:06:00 -070085 bool cont =
86 intf.forEachInstance([&](const auto& interface, const auto& instance, bool isRegex) {
87 // TODO(b/73556059): Store MatrixInstance as well to avoid creating temps
88 FqInstance fqInstance;
89 if (fqInstance.setTo(getName(), vr.majorVer, vr.minMinor, interface, instance)) {
Yifan Hong219000b2019-09-10 19:23:19 -070090 if (!func(MatrixInstance(format, std::move(fqInstance), VersionRange(vr),
91 optional, isRegex))) {
Yifan Hong7e9e04d2018-03-20 13:06:00 -070092 return false;
93 }
Yifan Hong2a90ffe2018-03-05 17:45:34 -080094 }
Yifan Hong7e9e04d2018-03-20 13:06:00 -070095 return true;
96 });
97 if (!cont) {
98 return false;
Yifan Hong2a90ffe2018-03-05 17:45:34 -080099 }
100 }
101 return true;
102}
103
Yifan Honge7e45532018-03-16 18:11:49 -0700104bool MatrixHal::forEachInstance(
105 const std::function<bool(const std::vector<VersionRange>&, const std::string&,
Yifan Hong7e9e04d2018-03-20 13:06:00 -0700106 const std::string&, bool isRegex)>& func) const {
Yifan Honge7e45532018-03-16 18:11:49 -0700107 for (const auto& intf : iterateValues(interfaces)) {
Yifan Hong7e9e04d2018-03-20 13:06:00 -0700108 bool cont =
109 intf.forEachInstance([&](const auto& interface, const auto& instance, bool isRegex) {
110 return func(this->versionRanges, interface, instance, isRegex);
111 });
112 if (!cont) {
113 return false;
Yifan Honge7e45532018-03-16 18:11:49 -0700114 }
115 }
116 return true;
117}
118
Yifan Hong075b3632018-03-14 16:03:11 -0700119bool MatrixHal::isCompatible(const std::set<FqInstance>& providedInstances,
120 const std::set<Version>& providedVersions) const {
121 // <version>'s are related by OR.
122 return std::any_of(versionRanges.begin(), versionRanges.end(), [&](const VersionRange& vr) {
123 return isCompatible(vr, providedInstances, providedVersions);
124 });
125}
126
127bool MatrixHal::isCompatible(const VersionRange& vr, const std::set<FqInstance>& providedInstances,
128 const std::set<Version>& providedVersions) const {
129 bool hasAnyInstance = false;
130 bool versionUnsatisfied = false;
131
132 // Look at each interface/instance, and ensure that they are in providedInstances.
133 forEachInstance(vr, [&](const MatrixInstance& matrixInstance) {
134 hasAnyInstance = true;
135
136 versionUnsatisfied |=
137 !std::any_of(providedInstances.begin(), providedInstances.end(),
138 [&](const FqInstance& providedInstance) {
139 return matrixInstance.isSatisfiedBy(providedInstance);
140 });
141
142 return !versionUnsatisfied; // if any interface/instance is unsatisfied, break
143 });
144
145 if (hasAnyInstance) {
146 return !versionUnsatisfied;
147 }
148
149 // In some cases (e.g. tests and native HALs), compatibility matrix doesn't specify
150 // any instances. Check versions only.
151 return std::any_of(
152 providedVersions.begin(), providedVersions.end(),
153 [&](const auto& providedVersion) { return vr.supportedBy(providedVersion); });
154}
155
Yifan Hong7967d7b2018-03-15 17:08:58 -0700156void MatrixHal::setOptional(bool o) {
157 this->optional = o;
158}
159
Yifan Honge7e45532018-03-16 18:11:49 -0700160void MatrixHal::insertVersionRanges(const std::vector<VersionRange>& other) {
161 for (const VersionRange& otherVr : other) {
Yifan Hong7967d7b2018-03-15 17:08:58 -0700162 auto existingVr = std::find_if(this->versionRanges.begin(), this->versionRanges.end(),
163 [&](const auto& e) { return e.overlaps(otherVr); });
164
165 if (existingVr == this->versionRanges.end()) {
166 this->versionRanges.push_back(otherVr);
167 } else {
Yifan Hong5da19c92018-03-15 17:11:43 -0700168 existingVr->minMinor = std::min(existingVr->minMinor, otherVr.minMinor);
Yifan Hong7967d7b2018-03-15 17:08:58 -0700169 existingVr->maxMinor = std::max(existingVr->maxMinor, otherVr.maxMinor);
170 }
171 }
172}
173
Yifan Hong643a9ef2018-03-21 14:13:55 -0700174void MatrixHal::insertInstance(const std::string& interface, const std::string& instance,
175 bool isRegex) {
Yifan Honge7e45532018-03-16 18:11:49 -0700176 auto it = interfaces.find(interface);
177 if (it == interfaces.end())
178 it = interfaces.emplace(interface, HalInterface{interface, {}}).first;
Yifan Hong643a9ef2018-03-21 14:13:55 -0700179 it->second.insertInstance(instance, isRegex);
Yifan Honge7e45532018-03-16 18:11:49 -0700180}
181
Yifan Hong7e9e04d2018-03-20 13:06:00 -0700182size_t MatrixHal::instancesCount() const {
183 size_t count = 0;
184 forEachInstance([&](const MatrixInstance&) {
185 ++count;
186 return true; // continue;
187 });
188 return count;
189}
190
Yifan Hong643a9ef2018-03-21 14:13:55 -0700191bool MatrixHal::removeInstance(const std::string& interface, const std::string& instance,
192 bool isRegex) {
Yifan Honge7e45532018-03-16 18:11:49 -0700193 auto it = interfaces.find(interface);
194 if (it == interfaces.end()) return false;
Yifan Hong643a9ef2018-03-21 14:13:55 -0700195 bool removed = it->second.removeInstance(instance, isRegex);
Yifan Hong7e9e04d2018-03-20 13:06:00 -0700196 if (!it->second.hasAnyInstance()) interfaces.erase(it);
197 return removed;
Yifan Honge7e45532018-03-16 18:11:49 -0700198}
199
200void MatrixHal::clearInstances() {
201 this->interfaces.clear();
202}
203
Yifan Hong676447a2016-11-15 12:57:23 -0800204} // namespace vintf
205} // namespace android