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