/* * 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. */ #include "ManifestHal.h" #include <unordered_set> #include "MapValueIterator.h" #include "parse_string.h" namespace android { namespace vintf { bool ManifestHal::isValid() const { std::unordered_set<size_t> existing; for (const auto &v : versions) { if (existing.find(v.majorVer) != existing.end()) { return false; } existing.insert(v.majorVer); } return transportArch.isValid(); } bool ManifestHal::operator==(const ManifestHal &other) const { if (format != other.format) return false; if (name != other.name) return false; if (versions != other.versions) return false; if (!(transportArch == other.transportArch)) return false; if (interfaces != other.interfaces) return false; if (isOverride() != other.isOverride()) return false; if (mAdditionalInstances != other.mAdditionalInstances) return false; return true; } bool ManifestHal::forEachInstance(const std::function<bool(const ManifestInstance&)>& func) const { for (const auto& v : versions) { for (const auto& intf : iterateValues(interfaces)) { bool cont = intf.forEachInstance([&](const auto& interface, const auto& instance, bool /* isRegex */) { // TODO(b/73556059): Store ManifestInstance as well to avoid creating temps FqInstance fqInstance; if (fqInstance.setTo(getName(), v.majorVer, v.minorVer, interface, instance)) { if (!func(ManifestInstance(std::move(fqInstance), TransportArch{transportArch}, format))) { return false; } } return true; }); if (!cont) { return false; } } } for (const auto& manifestInstance : mAdditionalInstances) { if (!func(manifestInstance)) { return false; } } return true; } bool ManifestHal::isDisabledHal() const { if (!isOverride()) return false; bool hasInstance = false; forEachInstance([&hasInstance](const auto&) { hasInstance = true; return false; // has at least one instance, stop here. }); return !hasInstance; } void ManifestHal::appendAllVersions(std::set<Version>* ret) const { ret->insert(versions.begin(), versions.end()); forEachInstance([&](const auto& e) { ret->insert(e.version()); return true; }); } static bool verifyInstances(const std::set<FqInstance>& fqInstances, std::string* error) { for (const FqInstance& fqInstance : fqInstances) { if (fqInstance.hasPackage()) { if (error) *error = "Should not specify package: \"" + fqInstance.string() + "\""; return false; } if (!fqInstance.hasVersion()) { if (error) *error = "Should specify version: \"" + fqInstance.string() + "\""; return false; } if (!fqInstance.hasInterface()) { if (error) *error = "Should specify interface: \"" + fqInstance.string() + "\""; return false; } if (!fqInstance.hasInstance()) { if (error) *error = "Should specify instance: \"" + fqInstance.string() + "\""; return false; } } return true; } bool ManifestHal::insertInstances(const std::set<FqInstance>& fqInstances, std::string* error) { if (!verifyInstances(fqInstances, error)) { return false; } for (const FqInstance& e : fqInstances) { FqInstance withPackage; if (!withPackage.setTo(this->getName(), e.getMajorVersion(), e.getMinorVersion(), e.getInterface(), e.getInstance())) { if (error) { *error = "Cannot create FqInstance with package='" + this->getName() + "', version='" + to_string(Version(e.getVersion())) + "', interface='" + e.getInterface() + "', instance='" + e.getInstance() + "'"; } return false; } mAdditionalInstances.emplace(std::move(withPackage), this->transportArch, this->format); } return true; } void ManifestHal::insertLegacyInstance(const std::string& interface, const std::string& instance) { auto it = interfaces.find(interface); if (it == interfaces.end()) it = interfaces.emplace(interface, HalInterface{interface, {}}).first; it->second.insertInstance(instance, false /* isRegex */); } } // namespace vintf } // namespace android