• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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 "ManifestHal.h"
18 #include <unordered_set>
19 
20 #include "MapValueIterator.h"
21 #include "parse_string.h"
22 
23 namespace android {
24 namespace vintf {
25 
isValid() const26 bool ManifestHal::isValid() const {
27     std::unordered_set<size_t> existing;
28     for (const auto &v : versions) {
29         if (existing.find(v.majorVer) != existing.end()) {
30             return false;
31         }
32         existing.insert(v.majorVer);
33     }
34     return transportArch.isValid();
35 }
36 
operator ==(const ManifestHal & other) const37 bool ManifestHal::operator==(const ManifestHal &other) const {
38     if (format != other.format)
39         return false;
40     if (name != other.name)
41         return false;
42     if (versions != other.versions)
43         return false;
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;
48     return true;
49 }
50 
forEachInstance(const std::function<bool (const ManifestInstance &)> & func) const51 bool ManifestHal::forEachInstance(const std::function<bool(const ManifestInstance&)>& func) const {
52     for (const auto& v : versions) {
53         for (const auto& intf : iterateValues(interfaces)) {
54             bool cont = intf.forEachInstance([&](const auto& interface, const auto& instance,
55                                                  bool /* isRegex */) {
56                 // TODO(b/73556059): Store ManifestInstance as well to avoid creating temps
57                 FqInstance fqInstance;
58                 if (fqInstance.setTo(getName(), v.majorVer, v.minorVer, interface, instance)) {
59                     if (!func(ManifestInstance(std::move(fqInstance), TransportArch{transportArch},
60                                                format))) {
61                         return false;
62                     }
63                 }
64                 return true;
65             });
66             if (!cont) {
67                 return false;
68             }
69         }
70     }
71 
72     for (const auto& manifestInstance : mAdditionalInstances) {
73         if (!func(manifestInstance)) {
74             return false;
75         }
76     }
77 
78     return true;
79 }
80 
isDisabledHal() const81 bool ManifestHal::isDisabledHal() const {
82     if (!isOverride()) return false;
83     bool hasInstance = false;
84     forEachInstance([&hasInstance](const auto&) {
85         hasInstance = true;
86         return false;  // has at least one instance, stop here.
87     });
88     return !hasInstance;
89 }
90 
appendAllVersions(std::set<Version> * ret) const91 void ManifestHal::appendAllVersions(std::set<Version>* ret) const {
92     ret->insert(versions.begin(), versions.end());
93     forEachInstance([&](const auto& e) {
94         ret->insert(e.version());
95         return true;
96     });
97 }
98 
verifyInstance(const FqInstance & fqInstance,std::string * error) const99 bool ManifestHal::verifyInstance(const FqInstance& fqInstance, std::string* error) const {
100     if (fqInstance.hasPackage() && fqInstance.getPackage() != this->getName()) {
101         if (error) {
102             *error = "Should not add \"" + fqInstance.string() + "\" to a HAL with name " +
103                      this->getName();
104         }
105         return false;
106     }
107     if (!fqInstance.hasVersion()) {
108         if (error) *error = "Should specify version: \"" + fqInstance.string() + "\"";
109         return false;
110     }
111     if (!fqInstance.hasInterface()) {
112         if (error) *error = "Should specify interface: \"" + fqInstance.string() + "\"";
113         return false;
114     }
115     if (!fqInstance.hasInstance()) {
116         if (error) *error = "Should specify instance: \"" + fqInstance.string() + "\"";
117         return false;
118     }
119     return true;
120 }
121 
insertInstances(const std::set<FqInstance> & fqInstances,std::string * error)122 bool ManifestHal::insertInstances(const std::set<FqInstance>& fqInstances, std::string* error) {
123     for (const FqInstance& e : fqInstances) {
124         if (!insertInstance(e, error)) {
125             return false;
126         }
127     }
128     return true;
129 }
130 
insertInstance(const FqInstance & e,std::string * error)131 bool ManifestHal::insertInstance(const FqInstance& e, std::string* error) {
132     if (!verifyInstance(e, error)) {
133         return false;
134     }
135 
136     size_t minorVer = e.getMinorVersion();
137     for (auto it = mAdditionalInstances.begin(); it != mAdditionalInstances.end();) {
138         if (it->version().majorVer == e.getMajorVersion() && it->interface() == e.getInterface() &&
139             it->instance() == e.getInstance()) {
140             minorVer = std::max(minorVer, it->version().minorVer);
141             it = mAdditionalInstances.erase(it);
142         } else {
143             ++it;
144         }
145     }
146 
147     FqInstance toAdd;
148     if (!toAdd.setTo(this->getName(), e.getMajorVersion(), minorVer, e.getInterface(),
149                      e.getInstance())) {
150         if (error) {
151             *error = "Cannot create FqInstance with package='" + this->getName() + "', version='" +
152                      to_string(Version(e.getMajorVersion(), minorVer)) + "', interface='" +
153                      e.getInterface() + "', instance='" + e.getInstance() + "'";
154         }
155         return false;
156     }
157 
158     mAdditionalInstances.emplace(std::move(toAdd), this->transportArch, this->format);
159     return true;
160 }
161 
162 } // namespace vintf
163 } // namespace android
164