• 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 <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:
~HalGroupHalGroup37     virtual ~HalGroup() {}
38 
39    protected:
40     // Get all hals with the given name (e.g "android.hardware.camera").
41     // There could be multiple hals that matches the same given name.
getHalsHalGroup42     std::vector<const Hal*> getHals(const std::string& name) const {
43         std::vector<const Hal*> ret;
44         auto range = mHals.equal_range(name);
45         for (auto it = range.first; it != range.second; ++it) {
46             ret.push_back(&it->second);
47         }
48         return ret;
49     }
50 
51     // Get all hals with the given name (e.g "android.hardware.camera").
52     // There could be multiple hals that matches the same given name.
53     // Non-const version of the above getHals() method.
getHalsHalGroup54     std::vector<Hal*> getHals(const std::string& name) {
55         std::vector<Hal*> ret;
56         auto range = mHals.equal_range(name);
57         for (auto it = range.first; it != range.second; ++it) {
58             ret.push_back(&it->second);
59         }
60         return ret;
61     }
62 
63    public:
64     // Apply func to all instances.
forEachInstanceHalGroup65     bool forEachInstance(const std::function<bool(const InstanceType&)>& func) const {
66         for (const auto& hal : getHals()) {
67             bool cont = hal.forEachInstance(func);
68             if (!cont) return false;
69         }
70         return true;
71     }
72 
forEachHidlInstanceHalGroup73     bool forEachHidlInstance(const std::function<bool(const InstanceType&)>& func) const {
74         return forEachInstance(HalFormat::HIDL, func);
75     }
76 
77    private:
forEachInstanceHalGroup78     bool forEachInstance(HalFormat format,
79                          const std::function<bool(const InstanceType&)>& func) const {
80         return forEachInstance([&](const InstanceType& e) {
81             if (e.format() == format) {
82                 return func(e);
83             }
84             return true;  // continue
85         });
86     }
87 
forEachInstanceOfPackageHalGroup88     bool forEachInstanceOfPackage(HalFormat format, const std::string& package,
89                                   const std::function<bool(const InstanceType&)>& func) const {
90         for (const auto* hal : getHals(package)) {
91             if (hal->format != format) {
92                 continue;
93             }
94             if (!hal->forEachInstance(func)) {
95                 return false;
96             }
97         }
98         return true;
99     }
forEachHidlInstanceOfPackageHalGroup100     bool forEachHidlInstanceOfPackage(const std::string& package,
101                                       const std::function<bool(const InstanceType&)>& func) const {
102         return forEachInstanceOfPackage(HalFormat::HIDL, package, func);
103     }
104 
105    protected:
106     // Apply func to all instances of package@expectVersion::*/*.
107     // For example, if a.h.foo@1.1::IFoo/default is in "this" and getHidlFqInstances
108     // is called with a.h.foo@1.0, then a.h.foo@1.1::IFoo/default is returned.
109     // If format is AIDL, expectVersion should be the fake AIDL version.
110     virtual bool forEachInstanceOfVersion(
111         HalFormat format, const std::string& package, const Version& expectVersion,
112         const std::function<bool(const InstanceType&)>& func) const = 0;
113 
114     // Apply func to instances of package@expectVersion::interface/*.
115     // For example, if a.h.foo@1.1::IFoo/default is in "this" and getHidlFqInstances
116     // is called with a.h.foo@1.0::IFoo, then a.h.foo@1.1::IFoo/default is returned.
117     // If format is AIDL, expectVersion should be the fake AIDL version.
forEachInstanceOfInterfaceHalGroup118     bool forEachInstanceOfInterface(HalFormat format, const std::string& package,
119                                     const Version& expectVersion, const std::string& interface,
120                                     const std::function<bool(const InstanceType&)>& func) const {
121         return forEachInstanceOfVersion(format, package, expectVersion,
122                                         [&func, &interface](const InstanceType& e) {
123                                             if (e.interface() == interface) {
124                                                 return func(e);
125                                             }
126                                             return true;
127                                         });
128     }
129 
130    public:
131     // Apply func to all instances of package@expectVersion::*/*.
132     // For example, if a.h.foo@1.1::IFoo/default is in "this" and getHidlFqInstances
133     // is called with a.h.foo@1.0, then a.h.foo@1.1::IFoo/default is returned.
forEachHidlInstanceOfVersionHalGroup134     virtual bool forEachHidlInstanceOfVersion(
135         const std::string& package, const Version& expectVersion,
136         const std::function<bool(const InstanceType&)>& func) const {
137         return forEachInstanceOfVersion(HalFormat::HIDL, package, expectVersion, func);
138     }
139 
140     // Apply func to instances of package@expectVersion::interface/*.
141     // For example, if a.h.foo@1.1::IFoo/default is in "this" and getHidlFqInstances
142     // is called with a.h.foo@1.0::IFoo, then a.h.foo@1.1::IFoo/default is returned.
forEachHidlInstanceOfInterfaceHalGroup143     bool forEachHidlInstanceOfInterface(
144         const std::string& package, const Version& expectVersion, const std::string& interface,
145         const std::function<bool(const InstanceType&)>& func) const {
146         return forEachInstanceOfInterface(HalFormat::HIDL, package, expectVersion, interface, func);
147     }
148 
149     // Alternative to forEachHidlInstanceOfInterface if you need a vector instead.
150     // If interface is empty, returns all instances of package@version;
151     // else return all instances of package@version::interface.
152     std::vector<InstanceType> getHidlFqInstances(const std::string& package,
153                                                  const Version& expectVersion,
154                                                  const std::string& interface = "") const {
155         std::vector<InstanceType> v;
156         auto mapToVector = [&v](const auto& e) {
157             v.push_back(e);
158             return true;
159         };
160         if (interface.empty()) {
161             (void)forEachHidlInstanceOfVersion(package, expectVersion, mapToVector);
162         } else {
163             (void)forEachHidlInstanceOfInterface(package, expectVersion, interface, mapToVector);
164         }
165         return v;
166     }
167 
168    protected:
169     // sorted map from component name to the component.
170     // The component name looks like: android.hardware.foo
171     std::multimap<std::string, Hal> mHals;
172 
173     // Return an iterable to all Hal objects. Call it as follows:
174     // for (const auto& e : vm.getHals()) { }
getHalsHalGroup175     ConstMultiMapValueIterable<std::string, Hal> getHals() const { return iterateValues(mHals); }
176 
177     // Return an iterable to all Hal objects. Call it as follows:
178     // for (const auto& e : vm.getHals()) { }
getHalsHalGroup179     MultiMapValueIterable<std::string, Hal> getHals() { return iterateValues(mHals); }
180 
181     // Get any HAL component based on the component name. Return any one
182     // if multiple. Return nullptr if the component does not exist. This is only
183     // for creating objects programatically.
184     // The component name looks like:
185     // android.hardware.foo
getAnyHalHalGroup186     Hal* getAnyHal(const std::string& name) {
187         auto it = mHals.find(name);
188         if (it == mHals.end()) {
189             return nullptr;
190         }
191         return &(it->second);
192     }
193 
194     // Helper for "add(Hal)". Returns pointer to inserted object. Never null.
addInternalHalGroup195     Hal* addInternal(Hal&& hal) {
196         std::string name = hal.getName();
197         auto it = mHals.emplace(std::move(name), std::move(hal));  // always succeeds
198         return &it->second;
199     }
200 
201     // Remove if shouldRemove(hal).
removeHalsIfHalGroup202     void removeHalsIf(const std::function<bool(const Hal&)>& shouldRemove) {
203         for (auto it = mHals.begin(); it != mHals.end();) {
204             const Hal& value = it->second;
205             if (shouldRemove(value)) {
206                 it = mHals.erase(it);
207             } else {
208                 ++it;
209             }
210         }
211     }
212 
213    private:
214     friend class AnalyzeMatrix;
215     friend class VintfObject;
216 };
217 
218 }  // namespace vintf
219 }  // namespace android
220 
221 #endif  // ANDROID_VINTF_HAL_GROUP_H
222