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 "MapValueIterator.h" 24 #include "Version.h" 25 26 namespace android { 27 namespace vintf { 28 29 // A HalGroup is a wrapped multimap from name to Hal. 30 // Hal.getName() must return a string indicating the name. 31 template <typename Hal> 32 struct HalGroup { 33 using InstanceType = typename Hal::InstanceType; 34 35 public: ~HalGroupHalGroup36 virtual ~HalGroup() {} 37 // Move all hals from another HalGroup to this. 38 bool addAllHals(HalGroup* other, std::string* error = nullptr) { 39 for (auto& pair : other->mHals) { 40 if (!add(std::move(pair.second))) { 41 if (error) { 42 *error = "HAL \"" + pair.first + "\" has a conflict."; 43 } 44 return false; 45 } 46 } 47 other->mHals.clear(); 48 return true; 49 } 50 51 // Add an hal to this HalGroup so that it can be constructed programatically. addHalGroup52 virtual bool add(Hal&& hal) { return addInternal(std::move(hal)) != nullptr; } 53 54 protected: 55 // Get all hals with the given name (e.g "android.hardware.camera"). 56 // There could be multiple hals that matches the same given name. getHalsHalGroup57 std::vector<const Hal*> getHals(const std::string& name) const { 58 std::vector<const 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 // Get all hals with the given name (e.g "android.hardware.camera"). 67 // There could be multiple hals that matches the same given name. 68 // Non-const version of the above getHals() method. getHalsHalGroup69 std::vector<Hal*> getHals(const std::string& name) { 70 std::vector<Hal*> ret; 71 auto range = mHals.equal_range(name); 72 for (auto it = range.first; it != range.second; ++it) { 73 ret.push_back(&it->second); 74 } 75 return ret; 76 } 77 78 public: 79 // Apply func to all instances. forEachInstanceHalGroup80 bool forEachInstance(const std::function<bool(const InstanceType&)>& func) const { 81 for (const auto& hal : getHals()) { 82 bool cont = hal.forEachInstance(func); 83 if (!cont) return false; 84 } 85 return true; 86 } 87 forEachInstanceOfPackageHalGroup88 bool forEachInstanceOfPackage(const std::string& package, 89 const std::function<bool(const InstanceType&)>& func) const { 90 for (const auto* hal : getHals(package)) { 91 if (!hal->forEachInstance(func)) { 92 return false; 93 } 94 } 95 return true; 96 } 97 98 // Apply func to all instances of package@expectVersion::*/*. 99 // For example, if a.h.foo@1.1::IFoo/default is in "this" and getFqInstances 100 // is called with a.h.foo@1.0, then a.h.foo@1.1::IFoo/default is returned. 101 virtual bool forEachInstanceOfVersion( 102 const std::string& package, const Version& expectVersion, 103 const std::function<bool(const InstanceType&)>& func) const = 0; 104 105 // Apply func to instances of package@expectVersion::interface/*. 106 // For example, if a.h.foo@1.1::IFoo/default is in "this" and getFqInstances 107 // is called with a.h.foo@1.0::IFoo, then a.h.foo@1.1::IFoo/default is returned. forEachInstanceOfInterfaceHalGroup108 bool forEachInstanceOfInterface(const std::string& package, const Version& expectVersion, 109 const std::string& interface, 110 const std::function<bool(const InstanceType&)>& func) const { 111 return forEachInstanceOfVersion(package, expectVersion, 112 [&func, &interface](const InstanceType& e) { 113 if (e.interface() == interface) { 114 return func(e); 115 } 116 return true; 117 }); 118 } 119 120 // Alternative to forEachInstanceOfInterface if you need a vector instead. 121 // If interface is empty, returns all instances of package@version; 122 // else return all instances of package@version::interface. 123 std::vector<InstanceType> getFqInstances(const std::string& package, 124 const Version& expectVersion, 125 const std::string& interface = "") const { 126 std::vector<InstanceType> v; 127 auto mapToVector = [&v](const auto& e) { 128 v.push_back(e); 129 return true; 130 }; 131 if (interface.empty()) { 132 (void)forEachInstanceOfVersion(package, expectVersion, mapToVector); 133 } else { 134 (void)forEachInstanceOfInterface(package, expectVersion, interface, mapToVector); 135 } 136 return v; 137 } 138 139 protected: 140 // sorted map from component name to the component. 141 // The component name looks like: android.hardware.foo 142 std::multimap<std::string, Hal> mHals; 143 144 // override this to filter for add. shouldAddHalGroup145 virtual bool shouldAdd(const Hal&) const { return true; } 146 147 // Return an iterable to all Hal objects. Call it as follows: 148 // for (const auto& e : vm.getHals()) { } getHalsHalGroup149 ConstMultiMapValueIterable<std::string, Hal> getHals() const { return iterateValues(mHals); } 150 151 // Return an iterable to all Hal objects. Call it as follows: 152 // for (const auto& e : vm.getHals()) { } getHalsHalGroup153 MultiMapValueIterable<std::string, Hal> getHals() { return iterateValues(mHals); } 154 155 // Get any HAL component based on the component name. Return any one 156 // if multiple. Return nullptr if the component does not exist. This is only 157 // for creating objects programatically. 158 // The component name looks like: 159 // android.hardware.foo getAnyHalHalGroup160 Hal* getAnyHal(const std::string& name) { 161 auto it = mHals.find(name); 162 if (it == mHals.end()) { 163 return nullptr; 164 } 165 return &(it->second); 166 } 167 addInternalHalGroup168 Hal* addInternal(Hal&& hal) { 169 if (!shouldAdd(hal)) { 170 return nullptr; 171 } 172 std::string name = hal.getName(); 173 auto it = mHals.emplace(std::move(name), std::move(hal)); // always succeeds 174 return &it->second; 175 } 176 }; 177 178 } // namespace vintf 179 } // namespace android 180 181 #endif // ANDROID_VINTF_HAL_GROUP_H 182