blob: 8307d1c5f502264fcdd6c19a54d664f5ab78d256 [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
Yifan Hong2a90ffe2018-03-05 17:45:34 -080046bool MatrixHal::forEachInstance(const std::function<bool(const MatrixInstance&)>& func) const {
47 for (const auto& vr : versionRanges) {
Yifan Hong075b3632018-03-14 16:03:11 -070048 if (!forEachInstance(vr, func)) {
49 return false;
50 }
51 }
52 return true;
53}
54
55bool MatrixHal::forEachInstance(const VersionRange& vr,
56 const std::function<bool(const MatrixInstance&)>& func) const {
57 for (const auto& intf : iterateValues(interfaces)) {
Yifan Hong7e9e04d2018-03-20 13:06:00 -070058 bool cont =
59 intf.forEachInstance([&](const auto& interface, const auto& instance, bool isRegex) {
60 // TODO(b/73556059): Store MatrixInstance as well to avoid creating temps
61 FqInstance fqInstance;
62 if (fqInstance.setTo(getName(), vr.majorVer, vr.minMinor, interface, instance)) {
Yifan Hong219000b2019-09-10 19:23:19 -070063 if (!func(MatrixInstance(format, std::move(fqInstance), VersionRange(vr),
64 optional, isRegex))) {
Yifan Hong7e9e04d2018-03-20 13:06:00 -070065 return false;
66 }
Yifan Hong2a90ffe2018-03-05 17:45:34 -080067 }
Yifan Hong7e9e04d2018-03-20 13:06:00 -070068 return true;
69 });
70 if (!cont) {
71 return false;
Yifan Hong2a90ffe2018-03-05 17:45:34 -080072 }
73 }
74 return true;
75}
76
Yifan Honge7e45532018-03-16 18:11:49 -070077bool MatrixHal::forEachInstance(
78 const std::function<bool(const std::vector<VersionRange>&, const std::string&,
Yifan Hong7e9e04d2018-03-20 13:06:00 -070079 const std::string&, bool isRegex)>& func) const {
Yifan Honge7e45532018-03-16 18:11:49 -070080 for (const auto& intf : iterateValues(interfaces)) {
Yifan Hong7e9e04d2018-03-20 13:06:00 -070081 bool cont =
82 intf.forEachInstance([&](const auto& interface, const auto& instance, bool isRegex) {
83 return func(this->versionRanges, interface, instance, isRegex);
84 });
85 if (!cont) {
86 return false;
Yifan Honge7e45532018-03-16 18:11:49 -070087 }
88 }
89 return true;
90}
91
Yifan Hong075b3632018-03-14 16:03:11 -070092bool MatrixHal::isCompatible(const std::set<FqInstance>& providedInstances,
93 const std::set<Version>& providedVersions) const {
94 // <version>'s are related by OR.
95 return std::any_of(versionRanges.begin(), versionRanges.end(), [&](const VersionRange& vr) {
96 return isCompatible(vr, providedInstances, providedVersions);
97 });
98}
99
100bool MatrixHal::isCompatible(const VersionRange& vr, const std::set<FqInstance>& providedInstances,
101 const std::set<Version>& providedVersions) const {
102 bool hasAnyInstance = false;
103 bool versionUnsatisfied = false;
104
105 // Look at each interface/instance, and ensure that they are in providedInstances.
106 forEachInstance(vr, [&](const MatrixInstance& matrixInstance) {
107 hasAnyInstance = true;
108
109 versionUnsatisfied |=
110 !std::any_of(providedInstances.begin(), providedInstances.end(),
111 [&](const FqInstance& providedInstance) {
112 return matrixInstance.isSatisfiedBy(providedInstance);
113 });
114
115 return !versionUnsatisfied; // if any interface/instance is unsatisfied, break
116 });
117
118 if (hasAnyInstance) {
119 return !versionUnsatisfied;
120 }
121
122 // In some cases (e.g. tests and native HALs), compatibility matrix doesn't specify
123 // any instances. Check versions only.
124 return std::any_of(
125 providedVersions.begin(), providedVersions.end(),
126 [&](const auto& providedVersion) { return vr.supportedBy(providedVersion); });
127}
128
Yifan Hong7967d7b2018-03-15 17:08:58 -0700129void MatrixHal::setOptional(bool o) {
130 this->optional = o;
131}
132
Yifan Honge7e45532018-03-16 18:11:49 -0700133void MatrixHal::insertVersionRanges(const std::vector<VersionRange>& other) {
134 for (const VersionRange& otherVr : other) {
Yifan Hong7967d7b2018-03-15 17:08:58 -0700135 auto existingVr = std::find_if(this->versionRanges.begin(), this->versionRanges.end(),
136 [&](const auto& e) { return e.overlaps(otherVr); });
137
138 if (existingVr == this->versionRanges.end()) {
139 this->versionRanges.push_back(otherVr);
140 } else {
Yifan Hong5da19c92018-03-15 17:11:43 -0700141 existingVr->minMinor = std::min(existingVr->minMinor, otherVr.minMinor);
Yifan Hong7967d7b2018-03-15 17:08:58 -0700142 existingVr->maxMinor = std::max(existingVr->maxMinor, otherVr.maxMinor);
143 }
144 }
145}
146
Yifan Hong643a9ef2018-03-21 14:13:55 -0700147void MatrixHal::insertInstance(const std::string& interface, const std::string& instance,
148 bool isRegex) {
Yifan Honge7e45532018-03-16 18:11:49 -0700149 auto it = interfaces.find(interface);
150 if (it == interfaces.end())
151 it = interfaces.emplace(interface, HalInterface{interface, {}}).first;
Yifan Hong643a9ef2018-03-21 14:13:55 -0700152 it->second.insertInstance(instance, isRegex);
Yifan Honge7e45532018-03-16 18:11:49 -0700153}
154
Yifan Hong7e9e04d2018-03-20 13:06:00 -0700155size_t MatrixHal::instancesCount() const {
156 size_t count = 0;
157 forEachInstance([&](const MatrixInstance&) {
158 ++count;
159 return true; // continue;
160 });
161 return count;
162}
163
Yifan Hong643a9ef2018-03-21 14:13:55 -0700164bool MatrixHal::removeInstance(const std::string& interface, const std::string& instance,
165 bool isRegex) {
Yifan Honge7e45532018-03-16 18:11:49 -0700166 auto it = interfaces.find(interface);
167 if (it == interfaces.end()) return false;
Yifan Hong643a9ef2018-03-21 14:13:55 -0700168 bool removed = it->second.removeInstance(instance, isRegex);
Yifan Hong7e9e04d2018-03-20 13:06:00 -0700169 if (!it->second.hasAnyInstance()) interfaces.erase(it);
170 return removed;
Yifan Honge7e45532018-03-16 18:11:49 -0700171}
172
173void MatrixHal::clearInstances() {
174 this->interfaces.clear();
175}
176
Yifan Hong676447a2016-11-15 12:57:23 -0800177} // namespace vintf
178} // namespace android