1 /*
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
19 #include <algorithm>
20
21 #include "MapValueIterator.h"
22 #include "constants-private.h"
23 #include "utils.h"
24
25 namespace android {
26 namespace vintf {
27
28 using details::convertLegacyInstanceIntoFqInstance;
29
isValid(std::string * error) const30 bool 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(
40 [&](const auto& interface, const auto& instance, bool /*isRegex*/) {
41 if (!convertLegacyInstanceIntoFqInstance(getName(), v, interface, instance,
42 format, error)
43 .has_value()) {
44 success = false;
45 }
46 return true; // continue
47 });
48 }
49 }
50 }
51
52 return success;
53 }
54
operator ==(const MatrixHal & other) const55 bool MatrixHal::operator==(const MatrixHal &other) const {
56 if (format != other.format)
57 return false;
58 if (name != other.name)
59 return false;
60 if (versionRanges != other.versionRanges)
61 return false;
62 if (interfaces != other.interfaces) return false;
63 return true;
64 }
65
containsVersion(const Version & version) const66 bool MatrixHal::containsVersion(const Version& version) const {
67 for (VersionRange vRange : versionRanges) {
68 if (vRange.contains(version)) return true;
69 }
70 return false;
71 }
72
forEachInstance(const std::function<bool (const MatrixInstance &)> & func) const73 bool MatrixHal::forEachInstance(const std::function<bool(const MatrixInstance&)>& func) const {
74 for (const auto& vr : versionRanges) {
75 if (!forEachInstance(vr, func)) {
76 return false;
77 }
78 }
79 return true;
80 }
81
forEachInstance(const VersionRange & vr,const std::function<bool (const MatrixInstance &)> & func) const82 bool MatrixHal::forEachInstance(const VersionRange& vr,
83 const std::function<bool(const MatrixInstance&)>& func) const {
84 for (const auto& intf : iterateValues(interfaces)) {
85 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)) {
90 if (!func(MatrixInstance(format, exclusiveTo, std::move(fqInstance),
91 VersionRange(vr), isRegex))) {
92 return false;
93 }
94 }
95 return true;
96 });
97 if (!cont) {
98 return false;
99 }
100 }
101 return true;
102 }
103
forEachInstance(const std::function<bool (const std::vector<VersionRange> &,const std::string &,const std::string &,bool isRegex)> & func) const104 bool MatrixHal::forEachInstance(
105 const std::function<bool(const std::vector<VersionRange>&, const std::string&,
106 const std::string&, bool isRegex)>& func) const {
107 for (const auto& intf : iterateValues(interfaces)) {
108 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;
114 }
115 }
116 return true;
117 }
118
insertVersionRanges(const std::vector<VersionRange> & other)119 void MatrixHal::insertVersionRanges(const std::vector<VersionRange>& other) {
120 for (const VersionRange& otherVr : other) {
121 auto existingVr = std::find_if(this->versionRanges.begin(), this->versionRanges.end(),
122 [&](const auto& e) { return e.overlaps(otherVr); });
123
124 if (existingVr == this->versionRanges.end()) {
125 this->versionRanges.push_back(otherVr);
126 } else {
127 existingVr->minMinor = std::min(existingVr->minMinor, otherVr.minMinor);
128 existingVr->maxMinor = std::max(existingVr->maxMinor, otherVr.maxMinor);
129 }
130 }
131 }
132
insertInstance(const std::string & interface,const std::string & instance,bool isRegex)133 void MatrixHal::insertInstance(const std::string& interface, const std::string& instance,
134 bool isRegex) {
135 auto it = interfaces.find(interface);
136 if (it == interfaces.end())
137 it = interfaces.emplace(interface, HalInterface{interface, {}}).first;
138 it->second.insertInstance(instance, isRegex);
139 }
140
instancesCount() const141 size_t MatrixHal::instancesCount() const {
142 size_t count = 0;
143 forEachInstance([&](const MatrixInstance&) {
144 ++count;
145 return true; // continue;
146 });
147 return count;
148 }
149
removeInstance(const std::string & interface,const std::string & instance,bool isRegex)150 bool MatrixHal::removeInstance(const std::string& interface, const std::string& instance,
151 bool isRegex) {
152 auto it = interfaces.find(interface);
153 if (it == interfaces.end()) return false;
154 bool removed = it->second.removeInstance(instance, isRegex);
155 if (!it->second.hasAnyInstance()) interfaces.erase(it);
156 return removed;
157 }
158
clearInstances()159 void MatrixHal::clearInstances() {
160 this->interfaces.clear();
161 }
162
163 } // namespace vintf
164 } // namespace android
165