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