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