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: 36 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 = pair.first; 43 } 44 return false; 45 } 46 } 47 return true; 48 } 49 50 // Add an hal to this HalGroup so that it can be constructed programatically. 51 virtual bool add(Hal&& hal) { return addInternal(std::move(hal)) != nullptr; } 52 53 // Get all hals with the given name (e.g "android.hardware.camera"). 54 // There could be multiple hals that matches the same given name. 55 // TODO(b/74247301) Deprecated; use forEachInstanceOfPackage instead. 56 std::vector<const Hal*> getHals(const std::string& name) const { 57 std::vector<const Hal*> ret; 58 auto range = mHals.equal_range(name); 59 for (auto it = range.first; it != range.second; ++it) { 60 ret.push_back(&it->second); 61 } 62 return ret; 63 } 64 65 // Get all hals with the given name (e.g "android.hardware.camera"). 66 // There could be multiple hals that matches the same given name. 67 // Non-const version of the above getHals() method. 68 // TODO(b/74247301) Deprecated; use forEachInstanceOfPackage instead. 69 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 // Apply func to all instances. 79 bool forEachInstance(const std::function<bool(const InstanceType&)>& func) const { 80 for (const auto& hal : getHals()) { 81 bool cont = hal.forEachInstance(func); 82 if (!cont) return false; 83 } 84 return true; 85 } 86 87 bool forEachInstanceOfPackage(const std::string& package, 88 const std::function<bool(const InstanceType&)>& func) const { 89 for (const auto* hal : getHals(package)) { 90 if (!hal->forEachInstance(func)) { 91 return false; 92 } 93 } 94 return true; 95 } 96 97 // Apply func to all instances of package@expectVersion::*/*. 98 // For example, if a.h.foo (at) 1.1::IFoo/default is in "this" and getFqInstances 99 // is called with a.h.foo (at) 1.0, then a.h.foo (at) 1.1::IFoo/default is returned. 100 virtual bool forEachInstanceOfVersion( 101 const std::string& package, const Version& expectVersion, 102 const std::function<bool(const InstanceType&)>& func) const = 0; 103 104 // Apply func to instances of package@expectVersion::interface/*. 105 // For example, if a.h.foo (at) 1.1::IFoo/default is in "this" and getFqInstances 106 // is called with a.h.foo (at) 1.0::IFoo, then a.h.foo (at) 1.1::IFoo/default is returned. 107 bool forEachInstanceOfInterface(const std::string& package, const Version& expectVersion, 108 const std::string& interface, 109 const std::function<bool(const InstanceType&)>& func) const { 110 return forEachInstanceOfVersion(package, expectVersion, 111 [&func, &interface](const InstanceType& e) { 112 if (e.interface() == interface) { 113 return func(e); 114 } 115 return true; 116 }); 117 } 118 119 // Alternative to forEachInstanceOfInterface if you need a vector instead. 120 // If interface is empty, returns all instances of package@version; 121 // else return all instances of package@version::interface. 122 std::vector<InstanceType> getFqInstances(const std::string& package, 123 const Version& expectVersion, 124 const std::string& interface = "") const { 125 std::vector<InstanceType> v; 126 auto mapToVector = [&v](const auto& e) { 127 v.push_back(e); 128 return true; 129 }; 130 if (interface.empty()) { 131 (void)forEachInstanceOfVersion(package, expectVersion, mapToVector); 132 } else { 133 (void)forEachInstanceOfInterface(package, expectVersion, interface, mapToVector); 134 } 135 return v; 136 } 137 138 protected: 139 // sorted map from component name to the component. 140 // The component name looks like: android.hardware.foo 141 std::multimap<std::string, Hal> mHals; 142 143 // override this to filter for add. 144 virtual bool shouldAdd(const Hal&) const { return true; } 145 146 // Return an iterable to all ManifestHal objects. Call it as follows: 147 // for (const auto& e : vm.getHals()) { } 148 ConstMultiMapValueIterable<std::string, Hal> getHals() const { 149 return ConstMultiMapValueIterable<std::string, Hal>(mHals); 150 } 151 152 // Get any HAL component based on the component name. Return any one 153 // if multiple. Return nullptr if the component does not exist. This is only 154 // for creating objects programatically. 155 // The component name looks like: 156 // android.hardware.foo 157 Hal* getAnyHal(const std::string& name) { 158 auto it = mHals.find(name); 159 if (it == mHals.end()) { 160 return nullptr; 161 } 162 return &(it->second); 163 } 164 165 Hal* addInternal(Hal&& hal) { 166 if (!shouldAdd(hal)) { 167 return nullptr; 168 } 169 std::string name = hal.getName(); 170 auto it = mHals.emplace(std::move(name), std::move(hal)); // always succeeds 171 return &it->second; 172 } 173 }; 174 175 } // namespace vintf 176 } // namespace android 177 178 #endif // ANDROID_VINTF_HAL_GROUP_H 179