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 "ExclusiveTo.h" 24 #include "HalFormat.h" 25 #include "MapValueIterator.h" 26 #include "Version.h" 27 28 namespace android { 29 namespace vintf { 30 31 // A HalGroup is a wrapped multimap from name to Hal. 32 // Hal.getName() must return a string indicating the name. 33 template <typename Hal> 34 struct HalGroup { 35 using InstanceType = typename Hal::InstanceType; 36 37 public: ~HalGroupHalGroup38 virtual ~HalGroup() {} 39 40 protected: 41 // Get all hals with the given name (e.g "android.hardware.camera"). 42 // There could be multiple hals that matches the same given name. getHalsHalGroup43 std::vector<const Hal*> getHals(const std::string& name) const { 44 std::vector<const Hal*> ret; 45 auto range = mHals.equal_range(name); 46 for (auto it = range.first; it != range.second; ++it) { 47 ret.push_back(&it->second); 48 } 49 return ret; 50 } 51 52 // Get all hals with the given name (e.g "android.hardware.camera"). 53 // There could be multiple hals that matches the same given name. 54 // Non-const version of the above getHals() method. getHalsHalGroup55 std::vector<Hal*> getHals(const std::string& name) { 56 std::vector<Hal*> ret; 57 auto range = mHals.equal_range(name); 58 for (auto it = range.first; it != range.second; ++it) { 59 ret.push_back(&it->second); 60 } 61 return ret; 62 } 63 64 public: 65 // Apply func to all instances. forEachInstanceHalGroup66 bool forEachInstance(const std::function<bool(const InstanceType&)>& func) const { 67 for (const auto& hal : getHals()) { 68 bool cont = hal.forEachInstance(func); 69 if (!cont) return false; 70 } 71 return true; 72 } 73 forEachHidlInstanceHalGroup74 bool forEachHidlInstance(const std::function<bool(const InstanceType&)>& func) const { 75 return forEachInstance(HalFormat::HIDL, func); 76 } 77 78 private: forEachInstanceHalGroup79 bool forEachInstance(HalFormat format, 80 const std::function<bool(const InstanceType&)>& func) const { 81 return forEachInstance([&](const InstanceType& e) { 82 if (e.format() == format) { 83 return func(e); 84 } 85 return true; // continue 86 }); 87 } 88 forEachInstanceOfPackageHalGroup89 bool forEachInstanceOfPackage(HalFormat format, ExclusiveTo exclusiveTo, 90 const std::string& package, 91 const std::function<bool(const InstanceType&)>& func) const { 92 for (const auto* hal : getHals(package)) { 93 if (hal->format != format) { 94 continue; 95 } 96 if (hal->exclusiveTo != exclusiveTo) { 97 continue; 98 } 99 if (!hal->forEachInstance(func)) { 100 return false; 101 } 102 } 103 return true; 104 } forEachHidlInstanceOfPackageHalGroup105 bool forEachHidlInstanceOfPackage(const std::string& package, 106 const std::function<bool(const InstanceType&)>& func) const { 107 return forEachInstanceOfPackage(HalFormat::HIDL, package, func); 108 } 109 110 protected: 111 // Apply func to all instances of package@expectVersion::*/*. 112 // For example, if [email protected]::IFoo/default is in "this" and getHidlFqInstances 113 // is called with [email protected], then [email protected]::IFoo/default is returned. 114 // If format is AIDL, expectVersion should be the fake AIDL version. 115 virtual bool forEachInstanceOfVersion( 116 HalFormat format, ExclusiveTo exclusiveTo, const std::string& package, 117 const Version& expectVersion, 118 const std::function<bool(const InstanceType&)>& func) const = 0; 119 120 // Apply func to instances of package@expectVersion::interface/*. 121 // For example, if [email protected]::IFoo/default is in "this" and getHidlFqInstances 122 // is called with [email protected]::IFoo, then [email protected]::IFoo/default is returned. 123 // If format is AIDL, expectVersion should be the fake AIDL version. forEachInstanceOfInterfaceHalGroup124 bool forEachInstanceOfInterface(HalFormat format, ExclusiveTo exclusiveTo, 125 const std::string& package, const Version& expectVersion, 126 const std::string& interface, 127 const std::function<bool(const InstanceType&)>& func) const { 128 return forEachInstanceOfVersion(format, exclusiveTo, package, expectVersion, 129 [&func, &interface](const InstanceType& e) { 130 if (e.interface() == interface) { 131 return func(e); 132 } 133 return true; 134 }); 135 } 136 137 public: 138 // Apply func to all instances of package@expectVersion::*/*. 139 // For example, if [email protected]::IFoo/default is in "this" and getHidlFqInstances 140 // is called with [email protected], then [email protected]::IFoo/default is returned. forEachHidlInstanceOfVersionHalGroup141 virtual bool forEachHidlInstanceOfVersion( 142 const std::string& package, const Version& expectVersion, 143 const std::function<bool(const InstanceType&)>& func) const { 144 return forEachInstanceOfVersion(HalFormat::HIDL, ExclusiveTo::EMPTY, package, expectVersion, 145 func); 146 } 147 148 // Apply func to instances of package@expectVersion::interface/*. 149 // For example, if [email protected]::IFoo/default is in "this" and getHidlFqInstances 150 // is called with [email protected]::IFoo, then [email protected]::IFoo/default is returned. forEachHidlInstanceOfInterfaceHalGroup151 bool forEachHidlInstanceOfInterface( 152 const std::string& package, const Version& expectVersion, const std::string& interface, 153 const std::function<bool(const InstanceType&)>& func) const { 154 return forEachInstanceOfInterface(HalFormat::HIDL, ExclusiveTo::EMPTY, package, 155 expectVersion, interface, func); 156 } 157 158 // Alternative to forEachHidlInstanceOfInterface if you need a vector instead. 159 // If interface is empty, returns all instances of package@version; 160 // else return all instances of package@version::interface. 161 std::vector<InstanceType> getHidlFqInstances(const std::string& package, 162 const Version& expectVersion, 163 const std::string& interface = "") const { 164 std::vector<InstanceType> v; 165 auto mapToVector = [&v](const auto& e) { 166 v.push_back(e); 167 return true; 168 }; 169 if (interface.empty()) { 170 (void)forEachHidlInstanceOfVersion(package, expectVersion, mapToVector); 171 } else { 172 (void)forEachHidlInstanceOfInterface(package, expectVersion, interface, mapToVector); 173 } 174 return v; 175 } 176 177 protected: 178 // sorted map from component name to the component. 179 // The component name looks like: android.hardware.foo 180 std::multimap<std::string, Hal> mHals; 181 182 // Return an iterable to all Hal objects. Call it as follows: 183 // for (const auto& e : vm.getHals()) { } getHalsHalGroup184 ConstMultiMapValueIterable<std::string, Hal> getHals() const { return iterateValues(mHals); } 185 186 // Return an iterable to all Hal objects. Call it as follows: 187 // for (const auto& e : vm.getHals()) { } getHalsHalGroup188 MultiMapValueIterable<std::string, Hal> getHals() { return iterateValues(mHals); } 189 190 // Get any HAL component based on the component name. Return any one 191 // if multiple. Return nullptr if the component does not exist. This is only 192 // for creating objects programatically. 193 // The component name looks like: 194 // android.hardware.foo getAnyHalHalGroup195 Hal* getAnyHal(const std::string& name) { 196 auto it = mHals.find(name); 197 if (it == mHals.end()) { 198 return nullptr; 199 } 200 return &(it->second); 201 } 202 203 // Helper for "add(Hal)". Returns pointer to inserted object. Never null. addInternalHalGroup204 Hal* addInternal(Hal&& hal) { 205 std::string name = hal.getName(); 206 auto it = mHals.emplace(std::move(name), std::move(hal)); // always succeeds 207 return &it->second; 208 } 209 210 // Remove if shouldRemove(hal). removeHalsIfHalGroup211 void removeHalsIf(const std::function<bool(const Hal&)>& shouldRemove) { 212 for (auto it = mHals.begin(); it != mHals.end();) { 213 const Hal& value = it->second; 214 if (shouldRemove(value)) { 215 it = mHals.erase(it); 216 } else { 217 ++it; 218 } 219 } 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