1*70a7ec85SAndroid Build Coastguard Worker /* 2*70a7ec85SAndroid Build Coastguard Worker * Copyright (C) 2017 The Android Open Source Project 3*70a7ec85SAndroid Build Coastguard Worker * 4*70a7ec85SAndroid Build Coastguard Worker * Licensed under the Apache License, Version 2.0 (the "License"); 5*70a7ec85SAndroid Build Coastguard Worker * you may not use this file except in compliance with the License. 6*70a7ec85SAndroid Build Coastguard Worker * You may obtain a copy of the License at 7*70a7ec85SAndroid Build Coastguard Worker * 8*70a7ec85SAndroid Build Coastguard Worker * http://www.apache.org/licenses/LICENSE-2.0 9*70a7ec85SAndroid Build Coastguard Worker * 10*70a7ec85SAndroid Build Coastguard Worker * Unless required by applicable law or agreed to in writing, software 11*70a7ec85SAndroid Build Coastguard Worker * distributed under the License is distributed on an "AS IS" BASIS, 12*70a7ec85SAndroid Build Coastguard Worker * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13*70a7ec85SAndroid Build Coastguard Worker * See the License for the specific language governing permissions and 14*70a7ec85SAndroid Build Coastguard Worker * limitations under the License. 15*70a7ec85SAndroid Build Coastguard Worker */ 16*70a7ec85SAndroid Build Coastguard Worker 17*70a7ec85SAndroid Build Coastguard Worker #ifndef ANDROID_VINTF_HAL_GROUP_H 18*70a7ec85SAndroid Build Coastguard Worker #define ANDROID_VINTF_HAL_GROUP_H 19*70a7ec85SAndroid Build Coastguard Worker 20*70a7ec85SAndroid Build Coastguard Worker #include <map> 21*70a7ec85SAndroid Build Coastguard Worker #include <set> 22*70a7ec85SAndroid Build Coastguard Worker 23*70a7ec85SAndroid Build Coastguard Worker #include "ExclusiveTo.h" 24*70a7ec85SAndroid Build Coastguard Worker #include "HalFormat.h" 25*70a7ec85SAndroid Build Coastguard Worker #include "MapValueIterator.h" 26*70a7ec85SAndroid Build Coastguard Worker #include "Version.h" 27*70a7ec85SAndroid Build Coastguard Worker 28*70a7ec85SAndroid Build Coastguard Worker namespace android { 29*70a7ec85SAndroid Build Coastguard Worker namespace vintf { 30*70a7ec85SAndroid Build Coastguard Worker 31*70a7ec85SAndroid Build Coastguard Worker // A HalGroup is a wrapped multimap from name to Hal. 32*70a7ec85SAndroid Build Coastguard Worker // Hal.getName() must return a string indicating the name. 33*70a7ec85SAndroid Build Coastguard Worker template <typename Hal> 34*70a7ec85SAndroid Build Coastguard Worker struct HalGroup { 35*70a7ec85SAndroid Build Coastguard Worker using InstanceType = typename Hal::InstanceType; 36*70a7ec85SAndroid Build Coastguard Worker 37*70a7ec85SAndroid Build Coastguard Worker public: ~HalGroupHalGroup38*70a7ec85SAndroid Build Coastguard Worker virtual ~HalGroup() {} 39*70a7ec85SAndroid Build Coastguard Worker 40*70a7ec85SAndroid Build Coastguard Worker protected: 41*70a7ec85SAndroid Build Coastguard Worker // Get all hals with the given name (e.g "android.hardware.camera"). 42*70a7ec85SAndroid Build Coastguard Worker // There could be multiple hals that matches the same given name. getHalsHalGroup43*70a7ec85SAndroid Build Coastguard Worker std::vector<const Hal*> getHals(const std::string& name) const { 44*70a7ec85SAndroid Build Coastguard Worker std::vector<const Hal*> ret; 45*70a7ec85SAndroid Build Coastguard Worker auto range = mHals.equal_range(name); 46*70a7ec85SAndroid Build Coastguard Worker for (auto it = range.first; it != range.second; ++it) { 47*70a7ec85SAndroid Build Coastguard Worker ret.push_back(&it->second); 48*70a7ec85SAndroid Build Coastguard Worker } 49*70a7ec85SAndroid Build Coastguard Worker return ret; 50*70a7ec85SAndroid Build Coastguard Worker } 51*70a7ec85SAndroid Build Coastguard Worker 52*70a7ec85SAndroid Build Coastguard Worker // Get all hals with the given name (e.g "android.hardware.camera"). 53*70a7ec85SAndroid Build Coastguard Worker // There could be multiple hals that matches the same given name. 54*70a7ec85SAndroid Build Coastguard Worker // Non-const version of the above getHals() method. getHalsHalGroup55*70a7ec85SAndroid Build Coastguard Worker std::vector<Hal*> getHals(const std::string& name) { 56*70a7ec85SAndroid Build Coastguard Worker std::vector<Hal*> ret; 57*70a7ec85SAndroid Build Coastguard Worker auto range = mHals.equal_range(name); 58*70a7ec85SAndroid Build Coastguard Worker for (auto it = range.first; it != range.second; ++it) { 59*70a7ec85SAndroid Build Coastguard Worker ret.push_back(&it->second); 60*70a7ec85SAndroid Build Coastguard Worker } 61*70a7ec85SAndroid Build Coastguard Worker return ret; 62*70a7ec85SAndroid Build Coastguard Worker } 63*70a7ec85SAndroid Build Coastguard Worker 64*70a7ec85SAndroid Build Coastguard Worker public: 65*70a7ec85SAndroid Build Coastguard Worker // Apply func to all instances. forEachInstanceHalGroup66*70a7ec85SAndroid Build Coastguard Worker bool forEachInstance(const std::function<bool(const InstanceType&)>& func) const { 67*70a7ec85SAndroid Build Coastguard Worker for (const auto& hal : getHals()) { 68*70a7ec85SAndroid Build Coastguard Worker bool cont = hal.forEachInstance(func); 69*70a7ec85SAndroid Build Coastguard Worker if (!cont) return false; 70*70a7ec85SAndroid Build Coastguard Worker } 71*70a7ec85SAndroid Build Coastguard Worker return true; 72*70a7ec85SAndroid Build Coastguard Worker } 73*70a7ec85SAndroid Build Coastguard Worker forEachHidlInstanceHalGroup74*70a7ec85SAndroid Build Coastguard Worker bool forEachHidlInstance(const std::function<bool(const InstanceType&)>& func) const { 75*70a7ec85SAndroid Build Coastguard Worker return forEachInstance(HalFormat::HIDL, func); 76*70a7ec85SAndroid Build Coastguard Worker } 77*70a7ec85SAndroid Build Coastguard Worker 78*70a7ec85SAndroid Build Coastguard Worker private: forEachInstanceHalGroup79*70a7ec85SAndroid Build Coastguard Worker bool forEachInstance(HalFormat format, 80*70a7ec85SAndroid Build Coastguard Worker const std::function<bool(const InstanceType&)>& func) const { 81*70a7ec85SAndroid Build Coastguard Worker return forEachInstance([&](const InstanceType& e) { 82*70a7ec85SAndroid Build Coastguard Worker if (e.format() == format) { 83*70a7ec85SAndroid Build Coastguard Worker return func(e); 84*70a7ec85SAndroid Build Coastguard Worker } 85*70a7ec85SAndroid Build Coastguard Worker return true; // continue 86*70a7ec85SAndroid Build Coastguard Worker }); 87*70a7ec85SAndroid Build Coastguard Worker } 88*70a7ec85SAndroid Build Coastguard Worker forEachInstanceOfPackageHalGroup89*70a7ec85SAndroid Build Coastguard Worker bool forEachInstanceOfPackage(HalFormat format, ExclusiveTo exclusiveTo, 90*70a7ec85SAndroid Build Coastguard Worker const std::string& package, 91*70a7ec85SAndroid Build Coastguard Worker const std::function<bool(const InstanceType&)>& func) const { 92*70a7ec85SAndroid Build Coastguard Worker for (const auto* hal : getHals(package)) { 93*70a7ec85SAndroid Build Coastguard Worker if (hal->format != format) { 94*70a7ec85SAndroid Build Coastguard Worker continue; 95*70a7ec85SAndroid Build Coastguard Worker } 96*70a7ec85SAndroid Build Coastguard Worker if (hal->exclusiveTo != exclusiveTo) { 97*70a7ec85SAndroid Build Coastguard Worker continue; 98*70a7ec85SAndroid Build Coastguard Worker } 99*70a7ec85SAndroid Build Coastguard Worker if (!hal->forEachInstance(func)) { 100*70a7ec85SAndroid Build Coastguard Worker return false; 101*70a7ec85SAndroid Build Coastguard Worker } 102*70a7ec85SAndroid Build Coastguard Worker } 103*70a7ec85SAndroid Build Coastguard Worker return true; 104*70a7ec85SAndroid Build Coastguard Worker } forEachHidlInstanceOfPackageHalGroup105*70a7ec85SAndroid Build Coastguard Worker bool forEachHidlInstanceOfPackage(const std::string& package, 106*70a7ec85SAndroid Build Coastguard Worker const std::function<bool(const InstanceType&)>& func) const { 107*70a7ec85SAndroid Build Coastguard Worker return forEachInstanceOfPackage(HalFormat::HIDL, package, func); 108*70a7ec85SAndroid Build Coastguard Worker } 109*70a7ec85SAndroid Build Coastguard Worker 110*70a7ec85SAndroid Build Coastguard Worker protected: 111*70a7ec85SAndroid Build Coastguard Worker // Apply func to all instances of package@expectVersion::*/*. 112*70a7ec85SAndroid Build Coastguard Worker // For example, if [email protected]::IFoo/default is in "this" and getHidlFqInstances 113*70a7ec85SAndroid Build Coastguard Worker // is called with [email protected], then [email protected]::IFoo/default is returned. 114*70a7ec85SAndroid Build Coastguard Worker // If format is AIDL, expectVersion should be the fake AIDL version. 115*70a7ec85SAndroid Build Coastguard Worker virtual bool forEachInstanceOfVersion( 116*70a7ec85SAndroid Build Coastguard Worker HalFormat format, ExclusiveTo exclusiveTo, const std::string& package, 117*70a7ec85SAndroid Build Coastguard Worker const Version& expectVersion, 118*70a7ec85SAndroid Build Coastguard Worker const std::function<bool(const InstanceType&)>& func) const = 0; 119*70a7ec85SAndroid Build Coastguard Worker 120*70a7ec85SAndroid Build Coastguard Worker // Apply func to instances of package@expectVersion::interface/*. 121*70a7ec85SAndroid Build Coastguard Worker // For example, if [email protected]::IFoo/default is in "this" and getHidlFqInstances 122*70a7ec85SAndroid Build Coastguard Worker // is called with [email protected]::IFoo, then [email protected]::IFoo/default is returned. 123*70a7ec85SAndroid Build Coastguard Worker // If format is AIDL, expectVersion should be the fake AIDL version. forEachInstanceOfInterfaceHalGroup124*70a7ec85SAndroid Build Coastguard Worker bool forEachInstanceOfInterface(HalFormat format, ExclusiveTo exclusiveTo, 125*70a7ec85SAndroid Build Coastguard Worker const std::string& package, const Version& expectVersion, 126*70a7ec85SAndroid Build Coastguard Worker const std::string& interface, 127*70a7ec85SAndroid Build Coastguard Worker const std::function<bool(const InstanceType&)>& func) const { 128*70a7ec85SAndroid Build Coastguard Worker return forEachInstanceOfVersion(format, exclusiveTo, package, expectVersion, 129*70a7ec85SAndroid Build Coastguard Worker [&func, &interface](const InstanceType& e) { 130*70a7ec85SAndroid Build Coastguard Worker if (e.interface() == interface) { 131*70a7ec85SAndroid Build Coastguard Worker return func(e); 132*70a7ec85SAndroid Build Coastguard Worker } 133*70a7ec85SAndroid Build Coastguard Worker return true; 134*70a7ec85SAndroid Build Coastguard Worker }); 135*70a7ec85SAndroid Build Coastguard Worker } 136*70a7ec85SAndroid Build Coastguard Worker 137*70a7ec85SAndroid Build Coastguard Worker public: 138*70a7ec85SAndroid Build Coastguard Worker // Apply func to all instances of package@expectVersion::*/*. 139*70a7ec85SAndroid Build Coastguard Worker // For example, if [email protected]::IFoo/default is in "this" and getHidlFqInstances 140*70a7ec85SAndroid Build Coastguard Worker // is called with [email protected], then [email protected]::IFoo/default is returned. forEachHidlInstanceOfVersionHalGroup141*70a7ec85SAndroid Build Coastguard Worker virtual bool forEachHidlInstanceOfVersion( 142*70a7ec85SAndroid Build Coastguard Worker const std::string& package, const Version& expectVersion, 143*70a7ec85SAndroid Build Coastguard Worker const std::function<bool(const InstanceType&)>& func) const { 144*70a7ec85SAndroid Build Coastguard Worker return forEachInstanceOfVersion(HalFormat::HIDL, ExclusiveTo::EMPTY, package, expectVersion, 145*70a7ec85SAndroid Build Coastguard Worker func); 146*70a7ec85SAndroid Build Coastguard Worker } 147*70a7ec85SAndroid Build Coastguard Worker 148*70a7ec85SAndroid Build Coastguard Worker // Apply func to instances of package@expectVersion::interface/*. 149*70a7ec85SAndroid Build Coastguard Worker // For example, if [email protected]::IFoo/default is in "this" and getHidlFqInstances 150*70a7ec85SAndroid Build Coastguard Worker // is called with [email protected]::IFoo, then [email protected]::IFoo/default is returned. forEachHidlInstanceOfInterfaceHalGroup151*70a7ec85SAndroid Build Coastguard Worker bool forEachHidlInstanceOfInterface( 152*70a7ec85SAndroid Build Coastguard Worker const std::string& package, const Version& expectVersion, const std::string& interface, 153*70a7ec85SAndroid Build Coastguard Worker const std::function<bool(const InstanceType&)>& func) const { 154*70a7ec85SAndroid Build Coastguard Worker return forEachInstanceOfInterface(HalFormat::HIDL, ExclusiveTo::EMPTY, package, 155*70a7ec85SAndroid Build Coastguard Worker expectVersion, interface, func); 156*70a7ec85SAndroid Build Coastguard Worker } 157*70a7ec85SAndroid Build Coastguard Worker 158*70a7ec85SAndroid Build Coastguard Worker // Alternative to forEachHidlInstanceOfInterface if you need a vector instead. 159*70a7ec85SAndroid Build Coastguard Worker // If interface is empty, returns all instances of package@version; 160*70a7ec85SAndroid Build Coastguard Worker // else return all instances of package@version::interface. 161*70a7ec85SAndroid Build Coastguard Worker std::vector<InstanceType> getHidlFqInstances(const std::string& package, 162*70a7ec85SAndroid Build Coastguard Worker const Version& expectVersion, 163*70a7ec85SAndroid Build Coastguard Worker const std::string& interface = "") const { 164*70a7ec85SAndroid Build Coastguard Worker std::vector<InstanceType> v; 165*70a7ec85SAndroid Build Coastguard Worker auto mapToVector = [&v](const auto& e) { 166*70a7ec85SAndroid Build Coastguard Worker v.push_back(e); 167*70a7ec85SAndroid Build Coastguard Worker return true; 168*70a7ec85SAndroid Build Coastguard Worker }; 169*70a7ec85SAndroid Build Coastguard Worker if (interface.empty()) { 170*70a7ec85SAndroid Build Coastguard Worker (void)forEachHidlInstanceOfVersion(package, expectVersion, mapToVector); 171*70a7ec85SAndroid Build Coastguard Worker } else { 172*70a7ec85SAndroid Build Coastguard Worker (void)forEachHidlInstanceOfInterface(package, expectVersion, interface, mapToVector); 173*70a7ec85SAndroid Build Coastguard Worker } 174*70a7ec85SAndroid Build Coastguard Worker return v; 175*70a7ec85SAndroid Build Coastguard Worker } 176*70a7ec85SAndroid Build Coastguard Worker 177*70a7ec85SAndroid Build Coastguard Worker protected: 178*70a7ec85SAndroid Build Coastguard Worker // sorted map from component name to the component. 179*70a7ec85SAndroid Build Coastguard Worker // The component name looks like: android.hardware.foo 180*70a7ec85SAndroid Build Coastguard Worker std::multimap<std::string, Hal> mHals; 181*70a7ec85SAndroid Build Coastguard Worker 182*70a7ec85SAndroid Build Coastguard Worker // Return an iterable to all Hal objects. Call it as follows: 183*70a7ec85SAndroid Build Coastguard Worker // for (const auto& e : vm.getHals()) { } getHalsHalGroup184*70a7ec85SAndroid Build Coastguard Worker ConstMultiMapValueIterable<std::string, Hal> getHals() const { return iterateValues(mHals); } 185*70a7ec85SAndroid Build Coastguard Worker 186*70a7ec85SAndroid Build Coastguard Worker // Return an iterable to all Hal objects. Call it as follows: 187*70a7ec85SAndroid Build Coastguard Worker // for (const auto& e : vm.getHals()) { } getHalsHalGroup188*70a7ec85SAndroid Build Coastguard Worker MultiMapValueIterable<std::string, Hal> getHals() { return iterateValues(mHals); } 189*70a7ec85SAndroid Build Coastguard Worker 190*70a7ec85SAndroid Build Coastguard Worker // Get any HAL component based on the component name. Return any one 191*70a7ec85SAndroid Build Coastguard Worker // if multiple. Return nullptr if the component does not exist. This is only 192*70a7ec85SAndroid Build Coastguard Worker // for creating objects programatically. 193*70a7ec85SAndroid Build Coastguard Worker // The component name looks like: 194*70a7ec85SAndroid Build Coastguard Worker // android.hardware.foo getAnyHalHalGroup195*70a7ec85SAndroid Build Coastguard Worker Hal* getAnyHal(const std::string& name) { 196*70a7ec85SAndroid Build Coastguard Worker auto it = mHals.find(name); 197*70a7ec85SAndroid Build Coastguard Worker if (it == mHals.end()) { 198*70a7ec85SAndroid Build Coastguard Worker return nullptr; 199*70a7ec85SAndroid Build Coastguard Worker } 200*70a7ec85SAndroid Build Coastguard Worker return &(it->second); 201*70a7ec85SAndroid Build Coastguard Worker } 202*70a7ec85SAndroid Build Coastguard Worker 203*70a7ec85SAndroid Build Coastguard Worker // Helper for "add(Hal)". Returns pointer to inserted object. Never null. addInternalHalGroup204*70a7ec85SAndroid Build Coastguard Worker Hal* addInternal(Hal&& hal) { 205*70a7ec85SAndroid Build Coastguard Worker std::string name = hal.getName(); 206*70a7ec85SAndroid Build Coastguard Worker auto it = mHals.emplace(std::move(name), std::move(hal)); // always succeeds 207*70a7ec85SAndroid Build Coastguard Worker return &it->second; 208*70a7ec85SAndroid Build Coastguard Worker } 209*70a7ec85SAndroid Build Coastguard Worker 210*70a7ec85SAndroid Build Coastguard Worker // Remove if shouldRemove(hal). removeHalsIfHalGroup211*70a7ec85SAndroid Build Coastguard Worker void removeHalsIf(const std::function<bool(const Hal&)>& shouldRemove) { 212*70a7ec85SAndroid Build Coastguard Worker for (auto it = mHals.begin(); it != mHals.end();) { 213*70a7ec85SAndroid Build Coastguard Worker const Hal& value = it->second; 214*70a7ec85SAndroid Build Coastguard Worker if (shouldRemove(value)) { 215*70a7ec85SAndroid Build Coastguard Worker it = mHals.erase(it); 216*70a7ec85SAndroid Build Coastguard Worker } else { 217*70a7ec85SAndroid Build Coastguard Worker ++it; 218*70a7ec85SAndroid Build Coastguard Worker } 219*70a7ec85SAndroid Build Coastguard Worker } 220*70a7ec85SAndroid Build Coastguard Worker } 221*70a7ec85SAndroid Build Coastguard Worker 222*70a7ec85SAndroid Build Coastguard Worker private: 223*70a7ec85SAndroid Build Coastguard Worker friend class AnalyzeMatrix; 224*70a7ec85SAndroid Build Coastguard Worker friend class VintfObject; 225*70a7ec85SAndroid Build Coastguard Worker }; 226*70a7ec85SAndroid Build Coastguard Worker 227*70a7ec85SAndroid Build Coastguard Worker } // namespace vintf 228*70a7ec85SAndroid Build Coastguard Worker } // namespace android 229*70a7ec85SAndroid Build Coastguard Worker 230*70a7ec85SAndroid Build Coastguard Worker #endif // ANDROID_VINTF_HAL_GROUP_H 231