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 #include "ManifestHal.h" 18 #include <unordered_set> 19 20 #include "MapValueIterator.h" 21 #include "parse_string.h" 22 23 namespace android { 24 namespace vintf { 25 26 bool ManifestHal::isValid() const { 27 std::unordered_set<size_t> existing; 28 for (const auto &v : versions) { 29 if (existing.find(v.majorVer) != existing.end()) { 30 return false; 31 } 32 existing.insert(v.majorVer); 33 } 34 return transportArch.isValid(); 35 } 36 37 bool ManifestHal::operator==(const ManifestHal &other) const { 38 if (format != other.format) 39 return false; 40 if (name != other.name) 41 return false; 42 if (versions != other.versions) 43 return false; 44 if (!(transportArch == other.transportArch)) return false; 45 if (interfaces != other.interfaces) return false; 46 if (isOverride() != other.isOverride()) return false; 47 if (mAdditionalInstances != other.mAdditionalInstances) return false; 48 return true; 49 } 50 51 bool ManifestHal::forEachInstance(const std::function<bool(const ManifestInstance&)>& func) const { 52 for (const auto& v : versions) { 53 for (const auto& intf : iterateValues(interfaces)) { 54 bool cont = intf.forEachInstance([&](const auto& interface, const auto& instance, 55 bool /* isRegex */) { 56 // TODO(b/73556059): Store ManifestInstance as well to avoid creating temps 57 FqInstance fqInstance; 58 if (fqInstance.setTo(getName(), v.majorVer, v.minorVer, interface, instance)) { 59 if (!func(ManifestInstance(std::move(fqInstance), TransportArch{transportArch}, 60 format))) { 61 return false; 62 } 63 } 64 return true; 65 }); 66 if (!cont) { 67 return false; 68 } 69 } 70 } 71 72 for (const auto& manifestInstance : mAdditionalInstances) { 73 if (!func(manifestInstance)) { 74 return false; 75 } 76 } 77 78 return true; 79 } 80 81 bool ManifestHal::isDisabledHal() const { 82 if (!isOverride()) return false; 83 bool hasInstance = false; 84 forEachInstance([&hasInstance](const auto&) { 85 hasInstance = true; 86 return false; // has at least one instance, stop here. 87 }); 88 return !hasInstance; 89 } 90 91 void ManifestHal::appendAllVersions(std::set<Version>* ret) const { 92 ret->insert(versions.begin(), versions.end()); 93 forEachInstance([&](const auto& e) { 94 ret->insert(e.version()); 95 return true; 96 }); 97 } 98 99 static bool verifyInstances(const std::set<FqInstance>& fqInstances, std::string* error) { 100 for (const FqInstance& fqInstance : fqInstances) { 101 if (fqInstance.hasPackage()) { 102 if (error) *error = "Should not specify package: \"" + fqInstance.string() + "\""; 103 return false; 104 } 105 if (!fqInstance.hasVersion()) { 106 if (error) *error = "Should specify version: \"" + fqInstance.string() + "\""; 107 return false; 108 } 109 if (!fqInstance.hasInterface()) { 110 if (error) *error = "Should specify interface: \"" + fqInstance.string() + "\""; 111 return false; 112 } 113 if (!fqInstance.hasInstance()) { 114 if (error) *error = "Should specify instance: \"" + fqInstance.string() + "\""; 115 return false; 116 } 117 } 118 return true; 119 } 120 121 bool ManifestHal::insertInstances(const std::set<FqInstance>& fqInstances, std::string* error) { 122 if (!verifyInstances(fqInstances, error)) { 123 return false; 124 } 125 126 for (const FqInstance& e : fqInstances) { 127 FqInstance withPackage; 128 if (!withPackage.setTo(this->getName(), e.getMajorVersion(), e.getMinorVersion(), 129 e.getInterface(), e.getInstance())) { 130 if (error) { 131 *error = "Cannot create FqInstance with package='" + this->getName() + 132 "', version='" + to_string(Version(e.getVersion())) + "', interface='" + 133 e.getInterface() + "', instance='" + e.getInstance() + "'"; 134 } 135 return false; 136 } 137 mAdditionalInstances.emplace(std::move(withPackage), this->transportArch, this->format); 138 } 139 140 return true; 141 } 142 143 void ManifestHal::insertLegacyInstance(const std::string& interface, const std::string& instance) { 144 auto it = interfaces.find(interface); 145 if (it == interfaces.end()) 146 it = interfaces.emplace(interface, HalInterface{interface, {}}).first; 147 it->second.insertInstance(instance, false /* isRegex */); 148 } 149 150 } // namespace vintf 151 } // namespace android 152