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