/* * Copyright (C) 2017 The Android Open Source Project * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ #ifndef ANDROID_VINTF_HAL_GROUP_H #define ANDROID_VINTF_HAL_GROUP_H #include #include #include "HalFormat.h" #include "MapValueIterator.h" #include "Version.h" namespace android { namespace vintf { // A HalGroup is a wrapped multimap from name to Hal. // Hal.getName() must return a string indicating the name. template struct HalGroup { using InstanceType = typename Hal::InstanceType; public: virtual ~HalGroup() {} // Add an hal to this HalGroup so that it can be constructed programatically. virtual bool add(Hal&& hal, std::string* error = nullptr) = 0; protected: // Get all hals with the given name (e.g "android.hardware.camera"). // There could be multiple hals that matches the same given name. std::vector getHals(const std::string& name) const { std::vector ret; auto range = mHals.equal_range(name); for (auto it = range.first; it != range.second; ++it) { ret.push_back(&it->second); } return ret; } // Get all hals with the given name (e.g "android.hardware.camera"). // There could be multiple hals that matches the same given name. // Non-const version of the above getHals() method. std::vector getHals(const std::string& name) { std::vector ret; auto range = mHals.equal_range(name); for (auto it = range.first; it != range.second; ++it) { ret.push_back(&it->second); } return ret; } public: // Apply func to all instances. bool forEachInstance(const std::function& func) const { for (const auto& hal : getHals()) { bool cont = hal.forEachInstance(func); if (!cont) return false; } return true; } bool forEachHidlInstance(const std::function& func) const { return forEachInstance(HalFormat::HIDL, func); } private: bool forEachInstance(HalFormat format, const std::function& func) const { return forEachInstance([&](const InstanceType& e) { if (e.format() == format) { return func(e); } return true; // continue }); } bool forEachInstanceOfPackage(HalFormat format, const std::string& package, const std::function& func) const { for (const auto* hal : getHals(package)) { if (hal->format != format) { continue; } if (!hal->forEachInstance(func)) { return false; } } return true; } bool forEachHidlInstanceOfPackage(const std::string& package, const std::function& func) const { return forEachInstanceOfPackage(HalFormat::HIDL, package, func); } protected: // Apply func to all instances of package@expectVersion::*/*. // For example, if a.h.foo@1.1::IFoo/default is in "this" and getHidlFqInstances // is called with a.h.foo@1.0, then a.h.foo@1.1::IFoo/default is returned. // If format is AIDL, expectVersion should be the fake AIDL version. virtual bool forEachInstanceOfVersion( HalFormat format, const std::string& package, const Version& expectVersion, const std::function& func) const = 0; // Apply func to instances of package@expectVersion::interface/*. // For example, if a.h.foo@1.1::IFoo/default is in "this" and getHidlFqInstances // is called with a.h.foo@1.0::IFoo, then a.h.foo@1.1::IFoo/default is returned. // If format is AIDL, expectVersion should be the fake AIDL version. bool forEachInstanceOfInterface(HalFormat format, const std::string& package, const Version& expectVersion, const std::string& interface, const std::function& func) const { return forEachInstanceOfVersion(format, package, expectVersion, [&func, &interface](const InstanceType& e) { if (e.interface() == interface) { return func(e); } return true; }); } public: // Apply func to all instances of package@expectVersion::*/*. // For example, if a.h.foo@1.1::IFoo/default is in "this" and getHidlFqInstances // is called with a.h.foo@1.0, then a.h.foo@1.1::IFoo/default is returned. virtual bool forEachHidlInstanceOfVersion( const std::string& package, const Version& expectVersion, const std::function& func) const { return forEachInstanceOfVersion(HalFormat::HIDL, package, expectVersion, func); } // Apply func to instances of package@expectVersion::interface/*. // For example, if a.h.foo@1.1::IFoo/default is in "this" and getHidlFqInstances // is called with a.h.foo@1.0::IFoo, then a.h.foo@1.1::IFoo/default is returned. bool forEachHidlInstanceOfInterface( const std::string& package, const Version& expectVersion, const std::string& interface, const std::function& func) const { return forEachInstanceOfInterface(HalFormat::HIDL, package, expectVersion, interface, func); } // Alternative to forEachHidlInstanceOfInterface if you need a vector instead. // If interface is empty, returns all instances of package@version; // else return all instances of package@version::interface. std::vector getHidlFqInstances(const std::string& package, const Version& expectVersion, const std::string& interface = "") const { std::vector v; auto mapToVector = [&v](const auto& e) { v.push_back(e); return true; }; if (interface.empty()) { (void)forEachHidlInstanceOfVersion(package, expectVersion, mapToVector); } else { (void)forEachHidlInstanceOfInterface(package, expectVersion, interface, mapToVector); } return v; } protected: // sorted map from component name to the component. // The component name looks like: android.hardware.foo std::multimap mHals; // Return an iterable to all Hal objects. Call it as follows: // for (const auto& e : vm.getHals()) { } ConstMultiMapValueIterable getHals() const { return iterateValues(mHals); } // Return an iterable to all Hal objects. Call it as follows: // for (const auto& e : vm.getHals()) { } MultiMapValueIterable getHals() { return iterateValues(mHals); } // Get any HAL component based on the component name. Return any one // if multiple. Return nullptr if the component does not exist. This is only // for creating objects programatically. // The component name looks like: // android.hardware.foo Hal* getAnyHal(const std::string& name) { auto it = mHals.find(name); if (it == mHals.end()) { return nullptr; } return &(it->second); } // Helper for "add(Hal)". Returns pointer to inserted object. Never null. Hal* addInternal(Hal&& hal) { std::string name = hal.getName(); auto it = mHals.emplace(std::move(name), std::move(hal)); // always succeeds return &it->second; } // Remove if shouldRemove(hal). void removeHalsIf(const std::function& shouldRemove) { for (auto it = mHals.begin(); it != mHals.end();) { const Hal& value = it->second; if (shouldRemove(value)) { it = mHals.erase(it); } else { ++it; } } } private: friend class AnalyzeMatrix; friend class VintfObject; }; } // namespace vintf } // namespace android #endif // ANDROID_VINTF_HAL_GROUP_H