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