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 #ifndef ANDROID_VINTF_HAL_GROUP_H
18 #define ANDROID_VINTF_HAL_GROUP_H
19 
20 #include <map>
21 #include <set>
22 
23 #include "HalFormat.h"
24 #include "MapValueIterator.h"
25 #include "Version.h"
26 
27 namespace android {
28 namespace vintf {
29 
30 // A HalGroup is a wrapped multimap from name to Hal.
31 // Hal.getName() must return a string indicating the name.
32 template <typename Hal>
33 struct HalGroup {
34     using InstanceType = typename Hal::InstanceType;
35 
36    public:
37     virtual ~HalGroup() {}
38     // Move all hals from another HalGroup to this.
39     bool addAllHals(HalGroup* other, std::string* error = nullptr) {
40         for (auto& pair : other->mHals) {
41             if (!add(std::move(pair.second))) {
42                 if (error) {
43                     *error = "HAL \"" + pair.first + "\" has a conflict.";
44                 }
45                 return false;
46             }
47         }
48         other->mHals.clear();
49         return true;
50     }
51 
52     // Add an hal to this HalGroup so that it can be constructed programatically.
53     virtual bool add(Hal&& hal) { return addInternal(std::move(hal)) != nullptr; }
54 
55    protected:
56     // Get all hals with the given name (e.g "android.hardware.camera").
57     // There could be multiple hals that matches the same given name.
58     std::vector<const Hal*> getHals(const std::string& name) const {
59         std::vector<const Hal*> ret;
60         auto range = mHals.equal_range(name);
61         for (auto it = range.first; it != range.second; ++it) {
62             ret.push_back(&it->second);
63         }
64         return ret;
65     }
66 
67     // Get all hals with the given name (e.g "android.hardware.camera").
68     // There could be multiple hals that matches the same given name.
69     // Non-const version of the above getHals() method.
70     std::vector<Hal*> getHals(const std::string& name) {
71         std::vector<Hal*> ret;
72         auto range = mHals.equal_range(name);
73         for (auto it = range.first; it != range.second; ++it) {
74             ret.push_back(&it->second);
75         }
76         return ret;
77     }
78 
79    public:
80     // Apply func to all instances.
81     bool forEachInstance(const std::function<bool(const InstanceType&)>& func) const {
82         for (const auto& hal : getHals()) {
83             bool cont = hal.forEachInstance(func);
84             if (!cont) return false;
85         }
86         return true;
87     }
88 
89     bool forEachHidlInstance(const std::function<bool(const InstanceType&)>& func) const {
90         return forEachInstance(HalFormat::HIDL, func);
91     }
92 
93    private:
94     bool forEachInstance(HalFormat format,
95                          const std::function<bool(const InstanceType&)>& func) const {
96         return forEachInstance([&](const InstanceType& e) {
97             if (e.format() == format) {
98                 return func(e);
99             }
100             return true;  // continue
101         });
102     }
103 
104     bool forEachInstanceOfPackage(HalFormat format, const std::string& package,
105                                   const std::function<bool(const InstanceType&)>& func) const {
106         for (const auto* hal : getHals(package)) {
107             if (hal->format != format) {
108                 continue;
109             }
110             if (!hal->forEachInstance(func)) {
111                 return false;
112             }
113         }
114         return true;
115     }
116     bool forEachHidlInstanceOfPackage(const std::string& package,
117                                       const std::function<bool(const InstanceType&)>& func) const {
118         return forEachInstanceOfPackage(HalFormat::HIDL, package, func);
119     }
120 
121    protected:
122     // Apply func to all instances of package@expectVersion::*/*.
123     // For example, if [email protected]::IFoo/default is in "this" and getHidlFqInstances
124     // is called with [email protected], then [email protected]::IFoo/default is returned.
125     // If format is AIDL, expectVersion should be the fake AIDL version.
126     virtual bool forEachInstanceOfVersion(
127         HalFormat format, const std::string& package, const Version& expectVersion,
128         const std::function<bool(const InstanceType&)>& func) const = 0;
129 
130     // Apply func to instances of package@expectVersion::interface/*.
131     // For example, if [email protected]::IFoo/default is in "this" and getHidlFqInstances
132     // is called with [email protected]::IFoo, then [email protected]::IFoo/default is returned.
133     // If format is AIDL, expectVersion should be the fake AIDL version.
134     bool forEachInstanceOfInterface(HalFormat format, const std::string& package,
135                                     const Version& expectVersion, const std::string& interface,
136                                     const std::function<bool(const InstanceType&)>& func) const {
137         return forEachInstanceOfVersion(format, package, expectVersion,
138                                         [&func, &interface](const InstanceType& e) {
139                                             if (e.interface() == interface) {
140                                                 return func(e);
141                                             }
142                                             return true;
143                                         });
144     }
145 
146    public:
147     // Apply func to all instances of package@expectVersion::*/*.
148     // For example, if [email protected]::IFoo/default is in "this" and getHidlFqInstances
149     // is called with [email protected], then [email protected]::IFoo/default is returned.
150     virtual bool forEachHidlInstanceOfVersion(
151         const std::string& package, const Version& expectVersion,
152         const std::function<bool(const InstanceType&)>& func) const {
153         return forEachInstanceOfVersion(HalFormat::HIDL, package, expectVersion, func);
154     }
155 
156     // Apply func to instances of package@expectVersion::interface/*.
157     // For example, if [email protected]::IFoo/default is in "this" and getHidlFqInstances
158     // is called with [email protected]::IFoo, then [email protected]::IFoo/default is returned.
159     bool forEachHidlInstanceOfInterface(
160         const std::string& package, const Version& expectVersion, const std::string& interface,
161         const std::function<bool(const InstanceType&)>& func) const {
162         return forEachInstanceOfInterface(HalFormat::HIDL, package, expectVersion, interface, func);
163     }
164 
165     // Alternative to forEachHidlInstanceOfInterface if you need a vector instead.
166     // If interface is empty, returns all instances of package@version;
167     // else return all instances of package@version::interface.
168     std::vector<InstanceType> getHidlFqInstances(const std::string& package,
169                                                  const Version& expectVersion,
170                                                  const std::string& interface = "") const {
171         std::vector<InstanceType> v;
172         auto mapToVector = [&v](const auto& e) {
173             v.push_back(e);
174             return true;
175         };
176         if (interface.empty()) {
177             (void)forEachHidlInstanceOfVersion(package, expectVersion, mapToVector);
178         } else {
179             (void)forEachHidlInstanceOfInterface(package, expectVersion, interface, mapToVector);
180         }
181         return v;
182     }
183 
184    protected:
185     // sorted map from component name to the component.
186     // The component name looks like: android.hardware.foo
187     std::multimap<std::string, Hal> mHals;
188 
189     // override this to filter for add.
190     virtual bool shouldAdd(const Hal&) const { return true; }
191 
192     // Return an iterable to all Hal objects. Call it as follows:
193     // for (const auto& e : vm.getHals()) { }
194     ConstMultiMapValueIterable<std::string, Hal> getHals() const { return iterateValues(mHals); }
195 
196     // Return an iterable to all Hal objects. Call it as follows:
197     // for (const auto& e : vm.getHals()) { }
198     MultiMapValueIterable<std::string, Hal> getHals() { return iterateValues(mHals); }
199 
200     // Get any HAL component based on the component name. Return any one
201     // if multiple. Return nullptr if the component does not exist. This is only
202     // for creating objects programatically.
203     // The component name looks like:
204     // android.hardware.foo
205     Hal* getAnyHal(const std::string& name) {
206         auto it = mHals.find(name);
207         if (it == mHals.end()) {
208             return nullptr;
209         }
210         return &(it->second);
211     }
212 
213     Hal* addInternal(Hal&& hal) {
214         if (!shouldAdd(hal)) {
215             return nullptr;
216         }
217         std::string name = hal.getName();
218         auto it = mHals.emplace(std::move(name), std::move(hal));  // always succeeds
219         return &it->second;
220     }
221 
222    private:
223     friend class AnalyzeMatrix;
224     friend class VintfObject;
225 };
226 
227 }  // namespace vintf
228 }  // namespace android
229 
230 #endif  // ANDROID_VINTF_HAL_GROUP_H
231