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