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 #define LOG_TAG "libvintf"
18*70a7ec85SAndroid Build Coastguard Worker #include <android-base/logging.h>
19*70a7ec85SAndroid Build Coastguard Worker
20*70a7ec85SAndroid Build Coastguard Worker #include "HalManifest.h"
21*70a7ec85SAndroid Build Coastguard Worker
22*70a7ec85SAndroid Build Coastguard Worker #include <dirent.h>
23*70a7ec85SAndroid Build Coastguard Worker
24*70a7ec85SAndroid Build Coastguard Worker #include <mutex>
25*70a7ec85SAndroid Build Coastguard Worker #include <set>
26*70a7ec85SAndroid Build Coastguard Worker
27*70a7ec85SAndroid Build Coastguard Worker #include <android-base/strings.h>
28*70a7ec85SAndroid Build Coastguard Worker
29*70a7ec85SAndroid Build Coastguard Worker #include "CompatibilityMatrix.h"
30*70a7ec85SAndroid Build Coastguard Worker #include "constants-private.h"
31*70a7ec85SAndroid Build Coastguard Worker #include "constants.h"
32*70a7ec85SAndroid Build Coastguard Worker #include "parse_string.h"
33*70a7ec85SAndroid Build Coastguard Worker #include "parse_xml.h"
34*70a7ec85SAndroid Build Coastguard Worker #include "utils.h"
35*70a7ec85SAndroid Build Coastguard Worker
36*70a7ec85SAndroid Build Coastguard Worker namespace android {
37*70a7ec85SAndroid Build Coastguard Worker namespace vintf {
38*70a7ec85SAndroid Build Coastguard Worker
39*70a7ec85SAndroid Build Coastguard Worker using details::Instances;
40*70a7ec85SAndroid Build Coastguard Worker using details::InstancesOfVersion;
41*70a7ec85SAndroid Build Coastguard Worker using details::mergeField;
42*70a7ec85SAndroid Build Coastguard Worker
43*70a7ec85SAndroid Build Coastguard Worker // Check <version> tag for all <hal> with the same name.
shouldAdd(const ManifestHal & hal,std::string * error) const44*70a7ec85SAndroid Build Coastguard Worker bool HalManifest::shouldAdd(const ManifestHal& hal, std::string* error) const {
45*70a7ec85SAndroid Build Coastguard Worker if (!hal.isValid(error)) {
46*70a7ec85SAndroid Build Coastguard Worker if (error) {
47*70a7ec85SAndroid Build Coastguard Worker error->insert(0, "HAL '" + hal.name + "' is not valid: ");
48*70a7ec85SAndroid Build Coastguard Worker if (!hal.fileName().empty()) {
49*70a7ec85SAndroid Build Coastguard Worker error->insert(0, "For file " + hal.fileName() + ": ");
50*70a7ec85SAndroid Build Coastguard Worker }
51*70a7ec85SAndroid Build Coastguard Worker }
52*70a7ec85SAndroid Build Coastguard Worker return false;
53*70a7ec85SAndroid Build Coastguard Worker }
54*70a7ec85SAndroid Build Coastguard Worker if (hal.isOverride()) {
55*70a7ec85SAndroid Build Coastguard Worker return true;
56*70a7ec85SAndroid Build Coastguard Worker }
57*70a7ec85SAndroid Build Coastguard Worker if (!addingConflictingMajorVersion(hal, error)) {
58*70a7ec85SAndroid Build Coastguard Worker return false;
59*70a7ec85SAndroid Build Coastguard Worker }
60*70a7ec85SAndroid Build Coastguard Worker return addingConflictingFqInstance(hal, error);
61*70a7ec85SAndroid Build Coastguard Worker }
62*70a7ec85SAndroid Build Coastguard Worker
addingConflictingMajorVersion(const ManifestHal & hal,std::string * error) const63*70a7ec85SAndroid Build Coastguard Worker bool HalManifest::addingConflictingMajorVersion(const ManifestHal& hal, std::string* error) const {
64*70a7ec85SAndroid Build Coastguard Worker // Skip checking for AIDL HALs because they all contain kFakeAidlMajorVersion.
65*70a7ec85SAndroid Build Coastguard Worker if (hal.format == HalFormat::AIDL) {
66*70a7ec85SAndroid Build Coastguard Worker return true;
67*70a7ec85SAndroid Build Coastguard Worker }
68*70a7ec85SAndroid Build Coastguard Worker
69*70a7ec85SAndroid Build Coastguard Worker auto existingHals = mHals.equal_range(hal.name);
70*70a7ec85SAndroid Build Coastguard Worker std::map<size_t, std::tuple<const ManifestHal*, Version>> existing;
71*70a7ec85SAndroid Build Coastguard Worker for (auto it = existingHals.first; it != existingHals.second; ++it) {
72*70a7ec85SAndroid Build Coastguard Worker const ManifestHal& existingHal = it->second;
73*70a7ec85SAndroid Build Coastguard Worker for (const auto& v : existingHal.versions) {
74*70a7ec85SAndroid Build Coastguard Worker // Assume integrity on existingHals, so no check on emplace().second
75*70a7ec85SAndroid Build Coastguard Worker existing.emplace(v.majorVer, std::make_tuple(&existingHal, v));
76*70a7ec85SAndroid Build Coastguard Worker }
77*70a7ec85SAndroid Build Coastguard Worker }
78*70a7ec85SAndroid Build Coastguard Worker bool success = true;
79*70a7ec85SAndroid Build Coastguard Worker for (const auto& v : hal.versions) {
80*70a7ec85SAndroid Build Coastguard Worker auto&& [existingIt, inserted] = existing.emplace(v.majorVer, std::make_tuple(&hal, v));
81*70a7ec85SAndroid Build Coastguard Worker if (inserted) {
82*70a7ec85SAndroid Build Coastguard Worker continue;
83*70a7ec85SAndroid Build Coastguard Worker }
84*70a7ec85SAndroid Build Coastguard Worker success = false;
85*70a7ec85SAndroid Build Coastguard Worker if (error) {
86*70a7ec85SAndroid Build Coastguard Worker auto&& [existingHal, existingVersion] = existingIt->second;
87*70a7ec85SAndroid Build Coastguard Worker *error = "Conflicting major version: " + to_string(existingVersion);
88*70a7ec85SAndroid Build Coastguard Worker if (!existingHal->fileName().empty()) {
89*70a7ec85SAndroid Build Coastguard Worker *error += " (from " + existingHal->fileName() + ")";
90*70a7ec85SAndroid Build Coastguard Worker }
91*70a7ec85SAndroid Build Coastguard Worker *error += " vs. " + to_string(v);
92*70a7ec85SAndroid Build Coastguard Worker if (!hal.fileName().empty()) {
93*70a7ec85SAndroid Build Coastguard Worker *error += " (from " + hal.fileName() + ")";
94*70a7ec85SAndroid Build Coastguard Worker }
95*70a7ec85SAndroid Build Coastguard Worker *error +=
96*70a7ec85SAndroid Build Coastguard Worker ". Check whether or not multiple modules providing the same HAL are installed.";
97*70a7ec85SAndroid Build Coastguard Worker }
98*70a7ec85SAndroid Build Coastguard Worker }
99*70a7ec85SAndroid Build Coastguard Worker
100*70a7ec85SAndroid Build Coastguard Worker return success;
101*70a7ec85SAndroid Build Coastguard Worker }
102*70a7ec85SAndroid Build Coastguard Worker
addingConflictingFqInstance(const ManifestHal & halToAdd,std::string * error) const103*70a7ec85SAndroid Build Coastguard Worker bool HalManifest::addingConflictingFqInstance(const ManifestHal& halToAdd,
104*70a7ec85SAndroid Build Coastguard Worker std::string* error) const {
105*70a7ec85SAndroid Build Coastguard Worker if (mSourceMetaVersion < kMetaVersionNoHalInterfaceInstance) {
106*70a7ec85SAndroid Build Coastguard Worker return true;
107*70a7ec85SAndroid Build Coastguard Worker }
108*70a7ec85SAndroid Build Coastguard Worker
109*70a7ec85SAndroid Build Coastguard Worker auto existingHals = mHals.equal_range(halToAdd.name);
110*70a7ec85SAndroid Build Coastguard Worker
111*70a7ec85SAndroid Build Coastguard Worker // Key: FqInstance with minor version 0
112*70a7ec85SAndroid Build Coastguard Worker // Value: original HAL and FqInstance
113*70a7ec85SAndroid Build Coastguard Worker std::map<FqInstance, std::tuple<const ManifestHal*, ManifestInstance>> existing;
114*70a7ec85SAndroid Build Coastguard Worker std::map<std::string, std::tuple<const ManifestHal*, ManifestInstance>> existingAccessors;
115*70a7ec85SAndroid Build Coastguard Worker for (auto it = existingHals.first; it != existingHals.second; ++it) {
116*70a7ec85SAndroid Build Coastguard Worker const ManifestHal& existingHal = it->second;
117*70a7ec85SAndroid Build Coastguard Worker bool success = existingHal.forEachInstance(
118*70a7ec85SAndroid Build Coastguard Worker [&existingHal, &existing, &existingAccessors](const auto& manifestInstance) {
119*70a7ec85SAndroid Build Coastguard Worker auto versionZero = manifestInstance.version().withMinor(0);
120*70a7ec85SAndroid Build Coastguard Worker auto key = manifestInstance.withVersion(versionZero).getFqInstance();
121*70a7ec85SAndroid Build Coastguard Worker // Assume integrity on existingHals, so no check on emplace().second
122*70a7ec85SAndroid Build Coastguard Worker existing.emplace(key, std::make_tuple(&existingHal, manifestInstance));
123*70a7ec85SAndroid Build Coastguard Worker if (auto accessor = manifestInstance.accessor(); accessor.has_value()) {
124*70a7ec85SAndroid Build Coastguard Worker existingAccessors.emplace(accessor.value(),
125*70a7ec85SAndroid Build Coastguard Worker std::make_tuple(&existingHal, manifestInstance));
126*70a7ec85SAndroid Build Coastguard Worker }
127*70a7ec85SAndroid Build Coastguard Worker return true; // continue
128*70a7ec85SAndroid Build Coastguard Worker });
129*70a7ec85SAndroid Build Coastguard Worker if (!success) {
130*70a7ec85SAndroid Build Coastguard Worker return false;
131*70a7ec85SAndroid Build Coastguard Worker }
132*70a7ec85SAndroid Build Coastguard Worker }
133*70a7ec85SAndroid Build Coastguard Worker return halToAdd.forEachInstance([&halToAdd, &existing, &existingAccessors,
134*70a7ec85SAndroid Build Coastguard Worker &error](const auto& manifestInstanceToAdd) {
135*70a7ec85SAndroid Build Coastguard Worker auto constructErrorMessage = [&halToAdd, &manifestInstanceToAdd](
136*70a7ec85SAndroid Build Coastguard Worker const auto& existingManifestInstance,
137*70a7ec85SAndroid Build Coastguard Worker const auto& existingHal) {
138*70a7ec85SAndroid Build Coastguard Worker std::string errorMsg = existingManifestInstance.descriptionWithoutPackage();
139*70a7ec85SAndroid Build Coastguard Worker if (!existingHal->fileName().empty()) {
140*70a7ec85SAndroid Build Coastguard Worker errorMsg += " (from " + existingHal->fileName() + ")";
141*70a7ec85SAndroid Build Coastguard Worker }
142*70a7ec85SAndroid Build Coastguard Worker errorMsg += " vs. " + manifestInstanceToAdd.descriptionWithoutPackage();
143*70a7ec85SAndroid Build Coastguard Worker if (!halToAdd.fileName().empty()) {
144*70a7ec85SAndroid Build Coastguard Worker errorMsg += " (from " + halToAdd.fileName() + ")";
145*70a7ec85SAndroid Build Coastguard Worker }
146*70a7ec85SAndroid Build Coastguard Worker return errorMsg;
147*70a7ec85SAndroid Build Coastguard Worker };
148*70a7ec85SAndroid Build Coastguard Worker
149*70a7ec85SAndroid Build Coastguard Worker auto versionZero = manifestInstanceToAdd.version().withMinor(0);
150*70a7ec85SAndroid Build Coastguard Worker auto key = manifestInstanceToAdd.withVersion(versionZero).getFqInstance();
151*70a7ec85SAndroid Build Coastguard Worker
152*70a7ec85SAndroid Build Coastguard Worker // Check duplicate FqInstance.
153*70a7ec85SAndroid Build Coastguard Worker auto&& [existingIt, inserted] =
154*70a7ec85SAndroid Build Coastguard Worker existing.emplace(key, std::make_tuple(&halToAdd, manifestInstanceToAdd));
155*70a7ec85SAndroid Build Coastguard Worker if (!inserted) {
156*70a7ec85SAndroid Build Coastguard Worker if (error) {
157*70a7ec85SAndroid Build Coastguard Worker auto&& [existingHal, existingManifestInstance] = existingIt->second;
158*70a7ec85SAndroid Build Coastguard Worker *error = "Conflicting FqInstance: ";
159*70a7ec85SAndroid Build Coastguard Worker *error += constructErrorMessage(existingManifestInstance, existingHal);
160*70a7ec85SAndroid Build Coastguard Worker *error +=
161*70a7ec85SAndroid Build Coastguard Worker ". Check whether or not multiple modules providing the same HAL are installed.";
162*70a7ec85SAndroid Build Coastguard Worker }
163*70a7ec85SAndroid Build Coastguard Worker return false; // break and let addingConflictingFqInstance return false
164*70a7ec85SAndroid Build Coastguard Worker }
165*70a7ec85SAndroid Build Coastguard Worker
166*70a7ec85SAndroid Build Coastguard Worker // Check duplicate accessor.
167*70a7ec85SAndroid Build Coastguard Worker auto accessor = manifestInstanceToAdd.accessor();
168*70a7ec85SAndroid Build Coastguard Worker if (!accessor.has_value()) {
169*70a7ec85SAndroid Build Coastguard Worker return true;
170*70a7ec85SAndroid Build Coastguard Worker }
171*70a7ec85SAndroid Build Coastguard Worker auto&& [existingAccessorIt, insertedAccessor] = existingAccessors.emplace(
172*70a7ec85SAndroid Build Coastguard Worker accessor.value(), std::make_tuple(&halToAdd, manifestInstanceToAdd));
173*70a7ec85SAndroid Build Coastguard Worker if (insertedAccessor) {
174*70a7ec85SAndroid Build Coastguard Worker return true;
175*70a7ec85SAndroid Build Coastguard Worker }
176*70a7ec85SAndroid Build Coastguard Worker if (error) {
177*70a7ec85SAndroid Build Coastguard Worker auto&& [existingHal, existingManifestInstance] = existingAccessorIt->second;
178*70a7ec85SAndroid Build Coastguard Worker *error = "Conflicting Accessor: ";
179*70a7ec85SAndroid Build Coastguard Worker *error += constructErrorMessage(existingManifestInstance, existingHal);
180*70a7ec85SAndroid Build Coastguard Worker *error +=
181*70a7ec85SAndroid Build Coastguard Worker ". Check whether or not multiple modules providing the same accessor are "
182*70a7ec85SAndroid Build Coastguard Worker "installed.";
183*70a7ec85SAndroid Build Coastguard Worker }
184*70a7ec85SAndroid Build Coastguard Worker return false; // break and let addingConflictingFqInstance return false
185*70a7ec85SAndroid Build Coastguard Worker });
186*70a7ec85SAndroid Build Coastguard Worker }
187*70a7ec85SAndroid Build Coastguard Worker
188*70a7ec85SAndroid Build Coastguard Worker // Remove elements from "list" if p(element) returns true.
189*70a7ec85SAndroid Build Coastguard Worker template <typename List, typename Predicate>
removeIf(List & list,Predicate predicate)190*70a7ec85SAndroid Build Coastguard Worker static void removeIf(List& list, Predicate predicate) {
191*70a7ec85SAndroid Build Coastguard Worker for (auto it = list.begin(); it != list.end();) {
192*70a7ec85SAndroid Build Coastguard Worker if (predicate(*it)) {
193*70a7ec85SAndroid Build Coastguard Worker it = list.erase(it);
194*70a7ec85SAndroid Build Coastguard Worker } else {
195*70a7ec85SAndroid Build Coastguard Worker ++it;
196*70a7ec85SAndroid Build Coastguard Worker }
197*70a7ec85SAndroid Build Coastguard Worker }
198*70a7ec85SAndroid Build Coastguard Worker }
199*70a7ec85SAndroid Build Coastguard Worker
removeHals(const std::string & name,size_t majorVer)200*70a7ec85SAndroid Build Coastguard Worker void HalManifest::removeHals(const std::string& name, size_t majorVer) {
201*70a7ec85SAndroid Build Coastguard Worker removeIf(mHals, [&name, majorVer](auto& existingHalPair) {
202*70a7ec85SAndroid Build Coastguard Worker auto& existingHal = existingHalPair.second;
203*70a7ec85SAndroid Build Coastguard Worker if (existingHal.name != name) {
204*70a7ec85SAndroid Build Coastguard Worker return false;
205*70a7ec85SAndroid Build Coastguard Worker }
206*70a7ec85SAndroid Build Coastguard Worker auto& existingVersions = existingHal.versions;
207*70a7ec85SAndroid Build Coastguard Worker removeIf(existingVersions, [majorVer](const auto& existingVersion) {
208*70a7ec85SAndroid Build Coastguard Worker return existingVersion.majorVer == majorVer;
209*70a7ec85SAndroid Build Coastguard Worker });
210*70a7ec85SAndroid Build Coastguard Worker auto& existingManifestInstances = existingHal.mManifestInstances;
211*70a7ec85SAndroid Build Coastguard Worker removeIf(existingManifestInstances, [majorVer](const auto& existingManifestInstance) {
212*70a7ec85SAndroid Build Coastguard Worker return existingManifestInstance.version().majorVer == majorVer;
213*70a7ec85SAndroid Build Coastguard Worker });
214*70a7ec85SAndroid Build Coastguard Worker return existingVersions.empty() && existingManifestInstances.empty();
215*70a7ec85SAndroid Build Coastguard Worker });
216*70a7ec85SAndroid Build Coastguard Worker }
217*70a7ec85SAndroid Build Coastguard Worker
add(ManifestHal && halToAdd,std::string * error)218*70a7ec85SAndroid Build Coastguard Worker bool HalManifest::add(ManifestHal&& halToAdd, std::string* error) {
219*70a7ec85SAndroid Build Coastguard Worker if (halToAdd.isOverride()) {
220*70a7ec85SAndroid Build Coastguard Worker if (halToAdd.isDisabledHal()) {
221*70a7ec85SAndroid Build Coastguard Worker // Special syntax when there are no instances at all. Remove all existing HALs
222*70a7ec85SAndroid Build Coastguard Worker // with the given name.
223*70a7ec85SAndroid Build Coastguard Worker mHals.erase(halToAdd.name);
224*70a7ec85SAndroid Build Coastguard Worker }
225*70a7ec85SAndroid Build Coastguard Worker // If there are <version> tags, remove all existing major versions that causes a conflict.
226*70a7ec85SAndroid Build Coastguard Worker for (const Version& versionToAdd : halToAdd.versions) {
227*70a7ec85SAndroid Build Coastguard Worker removeHals(halToAdd.name, versionToAdd.majorVer);
228*70a7ec85SAndroid Build Coastguard Worker }
229*70a7ec85SAndroid Build Coastguard Worker // If there are <fqname> tags, remove all existing major versions that causes a conflict.
230*70a7ec85SAndroid Build Coastguard Worker halToAdd.forEachInstance([this, &halToAdd](const auto& manifestInstanceToAdd) {
231*70a7ec85SAndroid Build Coastguard Worker removeHals(halToAdd.name, manifestInstanceToAdd.version().majorVer);
232*70a7ec85SAndroid Build Coastguard Worker return true; // continue
233*70a7ec85SAndroid Build Coastguard Worker });
234*70a7ec85SAndroid Build Coastguard Worker }
235*70a7ec85SAndroid Build Coastguard Worker
236*70a7ec85SAndroid Build Coastguard Worker if (!shouldAdd(halToAdd, error)) {
237*70a7ec85SAndroid Build Coastguard Worker return false;
238*70a7ec85SAndroid Build Coastguard Worker }
239*70a7ec85SAndroid Build Coastguard Worker
240*70a7ec85SAndroid Build Coastguard Worker CHECK(addInternal(std::move(halToAdd)) != nullptr);
241*70a7ec85SAndroid Build Coastguard Worker return true;
242*70a7ec85SAndroid Build Coastguard Worker }
243*70a7ec85SAndroid Build Coastguard Worker
addAllHals(HalManifest * other,std::string * error)244*70a7ec85SAndroid Build Coastguard Worker bool HalManifest::addAllHals(HalManifest* other, std::string* error) {
245*70a7ec85SAndroid Build Coastguard Worker for (auto& pair : other->mHals) {
246*70a7ec85SAndroid Build Coastguard Worker if (!add(std::move(pair.second), error)) {
247*70a7ec85SAndroid Build Coastguard Worker if (error) {
248*70a7ec85SAndroid Build Coastguard Worker error->insert(0, "HAL \"" + pair.first + "\" has a conflict: ");
249*70a7ec85SAndroid Build Coastguard Worker }
250*70a7ec85SAndroid Build Coastguard Worker return false;
251*70a7ec85SAndroid Build Coastguard Worker }
252*70a7ec85SAndroid Build Coastguard Worker }
253*70a7ec85SAndroid Build Coastguard Worker other->mHals.clear();
254*70a7ec85SAndroid Build Coastguard Worker return true;
255*70a7ec85SAndroid Build Coastguard Worker }
256*70a7ec85SAndroid Build Coastguard Worker
shouldAddXmlFile(const ManifestXmlFile & xmlFile) const257*70a7ec85SAndroid Build Coastguard Worker bool HalManifest::shouldAddXmlFile(const ManifestXmlFile& xmlFile) const {
258*70a7ec85SAndroid Build Coastguard Worker auto existingXmlFiles = getXmlFiles(xmlFile.name());
259*70a7ec85SAndroid Build Coastguard Worker for (auto it = existingXmlFiles.first; it != existingXmlFiles.second; ++it) {
260*70a7ec85SAndroid Build Coastguard Worker if (xmlFile.version() == it->second.version()) {
261*70a7ec85SAndroid Build Coastguard Worker return false;
262*70a7ec85SAndroid Build Coastguard Worker }
263*70a7ec85SAndroid Build Coastguard Worker }
264*70a7ec85SAndroid Build Coastguard Worker return true;
265*70a7ec85SAndroid Build Coastguard Worker }
266*70a7ec85SAndroid Build Coastguard Worker
getHalNames() const267*70a7ec85SAndroid Build Coastguard Worker std::set<std::string> HalManifest::getHalNames() const {
268*70a7ec85SAndroid Build Coastguard Worker std::set<std::string> names{};
269*70a7ec85SAndroid Build Coastguard Worker for (const auto &hal : mHals) {
270*70a7ec85SAndroid Build Coastguard Worker names.insert(hal.first);
271*70a7ec85SAndroid Build Coastguard Worker }
272*70a7ec85SAndroid Build Coastguard Worker return names;
273*70a7ec85SAndroid Build Coastguard Worker }
274*70a7ec85SAndroid Build Coastguard Worker
getHalNamesAndVersions() const275*70a7ec85SAndroid Build Coastguard Worker std::set<std::string> HalManifest::getHalNamesAndVersions() const {
276*70a7ec85SAndroid Build Coastguard Worker std::set<std::string> names{};
277*70a7ec85SAndroid Build Coastguard Worker forEachInstance([&names](const ManifestInstance& e) {
278*70a7ec85SAndroid Build Coastguard Worker names.insert(e.nameWithVersion());
279*70a7ec85SAndroid Build Coastguard Worker return true;
280*70a7ec85SAndroid Build Coastguard Worker });
281*70a7ec85SAndroid Build Coastguard Worker return names;
282*70a7ec85SAndroid Build Coastguard Worker }
283*70a7ec85SAndroid Build Coastguard Worker
getHidlTransport(const std::string & package,const Version & v,const std::string & interfaceName,const std::string & instanceName) const284*70a7ec85SAndroid Build Coastguard Worker Transport HalManifest::getHidlTransport(const std::string& package, const Version& v,
285*70a7ec85SAndroid Build Coastguard Worker const std::string& interfaceName,
286*70a7ec85SAndroid Build Coastguard Worker const std::string& instanceName) const {
287*70a7ec85SAndroid Build Coastguard Worker Transport transport{Transport::EMPTY};
288*70a7ec85SAndroid Build Coastguard Worker forEachInstanceOfInterface(HalFormat::HIDL, ExclusiveTo::EMPTY, package, v, interfaceName,
289*70a7ec85SAndroid Build Coastguard Worker [&](const auto& e) {
290*70a7ec85SAndroid Build Coastguard Worker if (e.instance() == instanceName) {
291*70a7ec85SAndroid Build Coastguard Worker transport = e.transport();
292*70a7ec85SAndroid Build Coastguard Worker }
293*70a7ec85SAndroid Build Coastguard Worker return transport == Transport::EMPTY; // if not found, continue
294*70a7ec85SAndroid Build Coastguard Worker });
295*70a7ec85SAndroid Build Coastguard Worker if (transport == Transport::EMPTY) {
296*70a7ec85SAndroid Build Coastguard Worker LOG(DEBUG) << "HalManifest::getHidlTransport(" << mType << "): Cannot find "
297*70a7ec85SAndroid Build Coastguard Worker << toFQNameString(package, v, interfaceName, instanceName);
298*70a7ec85SAndroid Build Coastguard Worker }
299*70a7ec85SAndroid Build Coastguard Worker return transport;
300*70a7ec85SAndroid Build Coastguard Worker }
301*70a7ec85SAndroid Build Coastguard Worker
forEachInstanceOfVersion(HalFormat format,ExclusiveTo exclusiveTo,const std::string & package,const Version & expectVersion,const std::function<bool (const ManifestInstance &)> & func) const302*70a7ec85SAndroid Build Coastguard Worker bool HalManifest::forEachInstanceOfVersion(
303*70a7ec85SAndroid Build Coastguard Worker HalFormat format, ExclusiveTo exclusiveTo, const std::string& package,
304*70a7ec85SAndroid Build Coastguard Worker const Version& expectVersion, const std::function<bool(const ManifestInstance&)>& func) const {
305*70a7ec85SAndroid Build Coastguard Worker for (const ManifestHal* hal : getHals(package)) {
306*70a7ec85SAndroid Build Coastguard Worker bool cont = hal->forEachInstance([&](const ManifestInstance& manifestInstance) {
307*70a7ec85SAndroid Build Coastguard Worker if (manifestInstance.format() == format &&
308*70a7ec85SAndroid Build Coastguard Worker manifestInstance.version().minorAtLeast(expectVersion) &&
309*70a7ec85SAndroid Build Coastguard Worker manifestInstance.exclusiveTo() == exclusiveTo) {
310*70a7ec85SAndroid Build Coastguard Worker return func(manifestInstance);
311*70a7ec85SAndroid Build Coastguard Worker }
312*70a7ec85SAndroid Build Coastguard Worker return true;
313*70a7ec85SAndroid Build Coastguard Worker });
314*70a7ec85SAndroid Build Coastguard Worker if (!cont) return false;
315*70a7ec85SAndroid Build Coastguard Worker }
316*70a7ec85SAndroid Build Coastguard Worker return true;
317*70a7ec85SAndroid Build Coastguard Worker }
318*70a7ec85SAndroid Build Coastguard Worker
forEachNativeInstance(const std::string & package,const std::function<bool (const ManifestInstance &)> & func) const319*70a7ec85SAndroid Build Coastguard Worker bool HalManifest::forEachNativeInstance(
320*70a7ec85SAndroid Build Coastguard Worker const std::string& package, const std::function<bool(const ManifestInstance&)>& func) const {
321*70a7ec85SAndroid Build Coastguard Worker for (const ManifestHal* hal : getHals(package)) {
322*70a7ec85SAndroid Build Coastguard Worker bool cont = hal->forEachInstance([&](const ManifestInstance& manifestInstance) {
323*70a7ec85SAndroid Build Coastguard Worker if (manifestInstance.format() == HalFormat::NATIVE) {
324*70a7ec85SAndroid Build Coastguard Worker return func(manifestInstance);
325*70a7ec85SAndroid Build Coastguard Worker }
326*70a7ec85SAndroid Build Coastguard Worker return true;
327*70a7ec85SAndroid Build Coastguard Worker });
328*70a7ec85SAndroid Build Coastguard Worker if (!cont) return false;
329*70a7ec85SAndroid Build Coastguard Worker }
330*70a7ec85SAndroid Build Coastguard Worker return true;
331*70a7ec85SAndroid Build Coastguard Worker }
332*70a7ec85SAndroid Build Coastguard Worker
333*70a7ec85SAndroid Build Coastguard Worker // indent = 2, {"foo"} => "foo"
334*70a7ec85SAndroid Build Coastguard Worker // indent = 2, {"foo", "bar"} => "\n foo\n bar";
335*70a7ec85SAndroid Build Coastguard Worker template <typename Container>
multilineIndent(std::ostream & os,size_t indent,const Container & lines)336*70a7ec85SAndroid Build Coastguard Worker void multilineIndent(std::ostream& os, size_t indent, const Container& lines) {
337*70a7ec85SAndroid Build Coastguard Worker if (lines.size() == 1) {
338*70a7ec85SAndroid Build Coastguard Worker os << *lines.begin();
339*70a7ec85SAndroid Build Coastguard Worker return;
340*70a7ec85SAndroid Build Coastguard Worker }
341*70a7ec85SAndroid Build Coastguard Worker for (const auto& line : lines) {
342*70a7ec85SAndroid Build Coastguard Worker os << "\n";
343*70a7ec85SAndroid Build Coastguard Worker for (size_t i = 0; i < indent; ++i) os << " ";
344*70a7ec85SAndroid Build Coastguard Worker os << line;
345*70a7ec85SAndroid Build Coastguard Worker }
346*70a7ec85SAndroid Build Coastguard Worker }
347*70a7ec85SAndroid Build Coastguard Worker
348*70a7ec85SAndroid Build Coastguard Worker // For each hal in mat, there must be a hal in manifest that supports this.
checkIncompatibleHals(const CompatibilityMatrix & mat) const349*70a7ec85SAndroid Build Coastguard Worker std::vector<std::string> HalManifest::checkIncompatibleHals(const CompatibilityMatrix& mat) const {
350*70a7ec85SAndroid Build Coastguard Worker std::vector<std::string> ret;
351*70a7ec85SAndroid Build Coastguard Worker for (const MatrixHal &matrixHal : mat.getHals()) {
352*70a7ec85SAndroid Build Coastguard Worker if (matrixHal.optional) {
353*70a7ec85SAndroid Build Coastguard Worker continue;
354*70a7ec85SAndroid Build Coastguard Worker }
355*70a7ec85SAndroid Build Coastguard Worker
356*70a7ec85SAndroid Build Coastguard Worker std::set<FqInstance> manifestInstances;
357*70a7ec85SAndroid Build Coastguard Worker std::set<std::string> manifestInstanceDesc;
358*70a7ec85SAndroid Build Coastguard Worker std::set<Version> versions;
359*70a7ec85SAndroid Build Coastguard Worker for (const ManifestHal* manifestHal : getHals(matrixHal.name)) {
360*70a7ec85SAndroid Build Coastguard Worker manifestHal->forEachInstance([&](const auto& manifestInstance) {
361*70a7ec85SAndroid Build Coastguard Worker manifestInstances.insert(manifestInstance.getFqInstance());
362*70a7ec85SAndroid Build Coastguard Worker manifestInstanceDesc.insert(manifestInstance.descriptionWithoutPackage());
363*70a7ec85SAndroid Build Coastguard Worker return true;
364*70a7ec85SAndroid Build Coastguard Worker });
365*70a7ec85SAndroid Build Coastguard Worker manifestHal->appendAllVersions(&versions);
366*70a7ec85SAndroid Build Coastguard Worker }
367*70a7ec85SAndroid Build Coastguard Worker
368*70a7ec85SAndroid Build Coastguard Worker if (!matrixHal.isCompatible(manifestInstances, versions)) {
369*70a7ec85SAndroid Build Coastguard Worker std::ostringstream oss;
370*70a7ec85SAndroid Build Coastguard Worker oss << matrixHal.name << ":\n required: ";
371*70a7ec85SAndroid Build Coastguard Worker multilineIndent(oss, 8, android::vintf::expandInstances(matrixHal));
372*70a7ec85SAndroid Build Coastguard Worker oss << "\n provided: ";
373*70a7ec85SAndroid Build Coastguard Worker if (manifestInstances.empty()) {
374*70a7ec85SAndroid Build Coastguard Worker multilineIndent(oss, 8, versions);
375*70a7ec85SAndroid Build Coastguard Worker } else {
376*70a7ec85SAndroid Build Coastguard Worker multilineIndent(oss, 8, manifestInstanceDesc);
377*70a7ec85SAndroid Build Coastguard Worker }
378*70a7ec85SAndroid Build Coastguard Worker
379*70a7ec85SAndroid Build Coastguard Worker ret.insert(ret.end(), oss.str());
380*70a7ec85SAndroid Build Coastguard Worker }
381*70a7ec85SAndroid Build Coastguard Worker }
382*70a7ec85SAndroid Build Coastguard Worker return ret;
383*70a7ec85SAndroid Build Coastguard Worker }
384*70a7ec85SAndroid Build Coastguard Worker
checkUnusedHals(const CompatibilityMatrix & mat,const std::vector<HidlInterfaceMetadata> & hidlMetadata) const385*70a7ec85SAndroid Build Coastguard Worker std::set<std::string> HalManifest::checkUnusedHals(
386*70a7ec85SAndroid Build Coastguard Worker const CompatibilityMatrix& mat, const std::vector<HidlInterfaceMetadata>& hidlMetadata) const {
387*70a7ec85SAndroid Build Coastguard Worker std::multimap<std::string, std::string> childrenMap;
388*70a7ec85SAndroid Build Coastguard Worker for (const auto& child : hidlMetadata) {
389*70a7ec85SAndroid Build Coastguard Worker for (const auto& parent : child.inherited) {
390*70a7ec85SAndroid Build Coastguard Worker childrenMap.emplace(parent, child.name);
391*70a7ec85SAndroid Build Coastguard Worker }
392*70a7ec85SAndroid Build Coastguard Worker }
393*70a7ec85SAndroid Build Coastguard Worker
394*70a7ec85SAndroid Build Coastguard Worker std::set<std::string> ret;
395*70a7ec85SAndroid Build Coastguard Worker
396*70a7ec85SAndroid Build Coastguard Worker forEachInstance([&ret, &mat, &childrenMap](const auto& manifestInstance) {
397*70a7ec85SAndroid Build Coastguard Worker if (mat.matchInstance(manifestInstance.format(), manifestInstance.exclusiveTo(),
398*70a7ec85SAndroid Build Coastguard Worker manifestInstance.package(), manifestInstance.version(),
399*70a7ec85SAndroid Build Coastguard Worker manifestInstance.interface(), manifestInstance.instance())) {
400*70a7ec85SAndroid Build Coastguard Worker // manifestInstance exactly matches an instance in |mat|.
401*70a7ec85SAndroid Build Coastguard Worker return true;
402*70a7ec85SAndroid Build Coastguard Worker }
403*70a7ec85SAndroid Build Coastguard Worker // For HIDL instances, If [email protected] inherits from [email protected], manifest may contain both, but
404*70a7ec85SAndroid Build Coastguard Worker // matrix may contain only 2.0 if 1.0 is considered deprecated. Hence, if manifestInstance
405*70a7ec85SAndroid Build Coastguard Worker // is 1.0, check all its children in the matrix too.
406*70a7ec85SAndroid Build Coastguard Worker // If there is at least one match, do not consider it unused.
407*70a7ec85SAndroid Build Coastguard Worker if (manifestInstance.format() == HalFormat::HIDL) {
408*70a7ec85SAndroid Build Coastguard Worker auto range =
409*70a7ec85SAndroid Build Coastguard Worker childrenMap.equal_range(manifestInstance.getFqInstance().getFqNameString());
410*70a7ec85SAndroid Build Coastguard Worker for (auto it = range.first; it != range.second; ++it) {
411*70a7ec85SAndroid Build Coastguard Worker details::FQName fqName;
412*70a7ec85SAndroid Build Coastguard Worker CHECK(fqName.setTo(it->second));
413*70a7ec85SAndroid Build Coastguard Worker if (mat.matchInstance(manifestInstance.format(), manifestInstance.exclusiveTo(),
414*70a7ec85SAndroid Build Coastguard Worker fqName.package(), fqName.getVersion(), fqName.name(),
415*70a7ec85SAndroid Build Coastguard Worker manifestInstance.instance())) {
416*70a7ec85SAndroid Build Coastguard Worker return true;
417*70a7ec85SAndroid Build Coastguard Worker }
418*70a7ec85SAndroid Build Coastguard Worker }
419*70a7ec85SAndroid Build Coastguard Worker }
420*70a7ec85SAndroid Build Coastguard Worker
421*70a7ec85SAndroid Build Coastguard Worker // If no match is found, consider it unused.
422*70a7ec85SAndroid Build Coastguard Worker ret.insert(manifestInstance.description());
423*70a7ec85SAndroid Build Coastguard Worker return true;
424*70a7ec85SAndroid Build Coastguard Worker });
425*70a7ec85SAndroid Build Coastguard Worker
426*70a7ec85SAndroid Build Coastguard Worker return ret;
427*70a7ec85SAndroid Build Coastguard Worker }
428*70a7ec85SAndroid Build Coastguard Worker
checkVendorNdkCompatibility(const VendorNdk & matVendorNdk,const std::vector<VendorNdk> & manifestVendorNdk,std::string * error)429*70a7ec85SAndroid Build Coastguard Worker static bool checkVendorNdkCompatibility(const VendorNdk& matVendorNdk,
430*70a7ec85SAndroid Build Coastguard Worker const std::vector<VendorNdk>& manifestVendorNdk,
431*70a7ec85SAndroid Build Coastguard Worker std::string* error) {
432*70a7ec85SAndroid Build Coastguard Worker // For pre-P vendor images, device compatibility matrix does not specify <vendor-ndk>
433*70a7ec85SAndroid Build Coastguard Worker // tag. Ignore the check for these devices.
434*70a7ec85SAndroid Build Coastguard Worker // VNDK is no longer a dependency for vendor version 35 and beyond. On these images,
435*70a7ec85SAndroid Build Coastguard Worker // <vendor-ndk> is also empty.
436*70a7ec85SAndroid Build Coastguard Worker if (matVendorNdk.version().empty()) {
437*70a7ec85SAndroid Build Coastguard Worker return true;
438*70a7ec85SAndroid Build Coastguard Worker }
439*70a7ec85SAndroid Build Coastguard Worker for (const auto& vndk : manifestVendorNdk) {
440*70a7ec85SAndroid Build Coastguard Worker if (vndk.version() != matVendorNdk.version()) {
441*70a7ec85SAndroid Build Coastguard Worker continue;
442*70a7ec85SAndroid Build Coastguard Worker }
443*70a7ec85SAndroid Build Coastguard Worker // version matches, check libraries
444*70a7ec85SAndroid Build Coastguard Worker std::vector<std::string> diff;
445*70a7ec85SAndroid Build Coastguard Worker std::set_difference(matVendorNdk.libraries().begin(), matVendorNdk.libraries().end(),
446*70a7ec85SAndroid Build Coastguard Worker vndk.libraries().begin(), vndk.libraries().end(),
447*70a7ec85SAndroid Build Coastguard Worker std::inserter(diff, diff.begin()));
448*70a7ec85SAndroid Build Coastguard Worker if (!diff.empty()) {
449*70a7ec85SAndroid Build Coastguard Worker if (error != nullptr) {
450*70a7ec85SAndroid Build Coastguard Worker *error = "Vndk libs incompatible for version " + matVendorNdk.version() +
451*70a7ec85SAndroid Build Coastguard Worker ". These libs are not in framework manifest:";
452*70a7ec85SAndroid Build Coastguard Worker for (const auto& name : diff) {
453*70a7ec85SAndroid Build Coastguard Worker *error += " " + name;
454*70a7ec85SAndroid Build Coastguard Worker }
455*70a7ec85SAndroid Build Coastguard Worker }
456*70a7ec85SAndroid Build Coastguard Worker return false;
457*70a7ec85SAndroid Build Coastguard Worker }
458*70a7ec85SAndroid Build Coastguard Worker return true;
459*70a7ec85SAndroid Build Coastguard Worker }
460*70a7ec85SAndroid Build Coastguard Worker
461*70a7ec85SAndroid Build Coastguard Worker // no match is found.
462*70a7ec85SAndroid Build Coastguard Worker if (error != nullptr) {
463*70a7ec85SAndroid Build Coastguard Worker *error = "Vndk version " + matVendorNdk.version() + " is not supported. " +
464*70a7ec85SAndroid Build Coastguard Worker "Supported versions in framework manifest are: [";
465*70a7ec85SAndroid Build Coastguard Worker for (const auto& vndk : manifestVendorNdk) {
466*70a7ec85SAndroid Build Coastguard Worker *error += " " + vndk.version();
467*70a7ec85SAndroid Build Coastguard Worker }
468*70a7ec85SAndroid Build Coastguard Worker *error += "]";
469*70a7ec85SAndroid Build Coastguard Worker }
470*70a7ec85SAndroid Build Coastguard Worker return false;
471*70a7ec85SAndroid Build Coastguard Worker }
472*70a7ec85SAndroid Build Coastguard Worker
checkSystemSdkCompatibility(const SystemSdk & matSystemSdk,const SystemSdk & manifestSystemSdk,std::string * error)473*70a7ec85SAndroid Build Coastguard Worker static bool checkSystemSdkCompatibility(const SystemSdk& matSystemSdk,
474*70a7ec85SAndroid Build Coastguard Worker const SystemSdk& manifestSystemSdk, std::string* error) {
475*70a7ec85SAndroid Build Coastguard Worker SystemSdk notSupported = matSystemSdk.removeVersions(manifestSystemSdk);
476*70a7ec85SAndroid Build Coastguard Worker if (!notSupported.empty()) {
477*70a7ec85SAndroid Build Coastguard Worker if (error) {
478*70a7ec85SAndroid Build Coastguard Worker *error =
479*70a7ec85SAndroid Build Coastguard Worker "The following System SDK versions are required by device "
480*70a7ec85SAndroid Build Coastguard Worker "compatibility matrix but not supported by the framework manifest: [" +
481*70a7ec85SAndroid Build Coastguard Worker base::Join(notSupported.versions(), ", ") + "]. Supported versions are: [" +
482*70a7ec85SAndroid Build Coastguard Worker base::Join(manifestSystemSdk.versions(), ", ") + "].";
483*70a7ec85SAndroid Build Coastguard Worker }
484*70a7ec85SAndroid Build Coastguard Worker return false;
485*70a7ec85SAndroid Build Coastguard Worker }
486*70a7ec85SAndroid Build Coastguard Worker return true;
487*70a7ec85SAndroid Build Coastguard Worker }
488*70a7ec85SAndroid Build Coastguard Worker
checkCompatibility(const CompatibilityMatrix & mat,std::string * error,CheckFlags::Type flags) const489*70a7ec85SAndroid Build Coastguard Worker bool HalManifest::checkCompatibility(const CompatibilityMatrix& mat, std::string* error,
490*70a7ec85SAndroid Build Coastguard Worker CheckFlags::Type flags) const {
491*70a7ec85SAndroid Build Coastguard Worker if (mType == mat.mType) {
492*70a7ec85SAndroid Build Coastguard Worker if (error != nullptr) {
493*70a7ec85SAndroid Build Coastguard Worker *error = "Wrong type; checking " + to_string(mType) + " manifest against "
494*70a7ec85SAndroid Build Coastguard Worker + to_string(mat.mType) + " compatibility matrix";
495*70a7ec85SAndroid Build Coastguard Worker }
496*70a7ec85SAndroid Build Coastguard Worker return false;
497*70a7ec85SAndroid Build Coastguard Worker }
498*70a7ec85SAndroid Build Coastguard Worker auto incompatibleHals = checkIncompatibleHals(mat);
499*70a7ec85SAndroid Build Coastguard Worker if (!incompatibleHals.empty()) {
500*70a7ec85SAndroid Build Coastguard Worker if (error != nullptr) {
501*70a7ec85SAndroid Build Coastguard Worker *error = "HALs incompatible.";
502*70a7ec85SAndroid Build Coastguard Worker if (mat.level() != Level::UNSPECIFIED)
503*70a7ec85SAndroid Build Coastguard Worker *error += " Matrix level = " + to_string(mat.level()) + ".";
504*70a7ec85SAndroid Build Coastguard Worker if (level() != Level::UNSPECIFIED)
505*70a7ec85SAndroid Build Coastguard Worker *error += " Manifest level = " + to_string(level()) + ".";
506*70a7ec85SAndroid Build Coastguard Worker *error += " The following requirements are not met:\n";
507*70a7ec85SAndroid Build Coastguard Worker for (const auto& e : incompatibleHals) {
508*70a7ec85SAndroid Build Coastguard Worker *error += e + "\n";
509*70a7ec85SAndroid Build Coastguard Worker }
510*70a7ec85SAndroid Build Coastguard Worker }
511*70a7ec85SAndroid Build Coastguard Worker return false;
512*70a7ec85SAndroid Build Coastguard Worker }
513*70a7ec85SAndroid Build Coastguard Worker if (mType == SchemaType::FRAMEWORK) {
514*70a7ec85SAndroid Build Coastguard Worker if (!checkVendorNdkCompatibility(mat.device.mVendorNdk, framework.mVendorNdks, error)) {
515*70a7ec85SAndroid Build Coastguard Worker return false;
516*70a7ec85SAndroid Build Coastguard Worker }
517*70a7ec85SAndroid Build Coastguard Worker
518*70a7ec85SAndroid Build Coastguard Worker if (!checkSystemSdkCompatibility(mat.device.mSystemSdk, framework.mSystemSdk, error)) {
519*70a7ec85SAndroid Build Coastguard Worker return false;
520*70a7ec85SAndroid Build Coastguard Worker }
521*70a7ec85SAndroid Build Coastguard Worker } else if (mType == SchemaType::DEVICE) {
522*70a7ec85SAndroid Build Coastguard Worker bool sepolicyMatch = false;
523*70a7ec85SAndroid Build Coastguard Worker for (const auto &range : mat.framework.mSepolicy.sepolicyVersions()) {
524*70a7ec85SAndroid Build Coastguard Worker if (range.supportedBy(device.mSepolicyVersion)) {
525*70a7ec85SAndroid Build Coastguard Worker sepolicyMatch = true;
526*70a7ec85SAndroid Build Coastguard Worker break;
527*70a7ec85SAndroid Build Coastguard Worker }
528*70a7ec85SAndroid Build Coastguard Worker }
529*70a7ec85SAndroid Build Coastguard Worker if (!sepolicyMatch) {
530*70a7ec85SAndroid Build Coastguard Worker if (error != nullptr) {
531*70a7ec85SAndroid Build Coastguard Worker *error = "Sepolicy version " + to_string(device.mSepolicyVersion)
532*70a7ec85SAndroid Build Coastguard Worker + " doesn't satisify the requirements.";
533*70a7ec85SAndroid Build Coastguard Worker }
534*70a7ec85SAndroid Build Coastguard Worker return false;
535*70a7ec85SAndroid Build Coastguard Worker }
536*70a7ec85SAndroid Build Coastguard Worker
537*70a7ec85SAndroid Build Coastguard Worker // Not using inferredKernelLevel() to preserve the legacy behavior if <kernel> does not have
538*70a7ec85SAndroid Build Coastguard Worker // level attribute.
539*70a7ec85SAndroid Build Coastguard Worker // Note that shouldCheckKernelCompatibility() only returns true on host, because the
540*70a7ec85SAndroid Build Coastguard Worker // on-device HalManifest does not have kernel version set. On the device, kernel information
541*70a7ec85SAndroid Build Coastguard Worker // is retrieved from RuntimeInfo.
542*70a7ec85SAndroid Build Coastguard Worker Level kernelTagLevel = kernel()->level();
543*70a7ec85SAndroid Build Coastguard Worker if (flags.isKernelEnabled() && shouldCheckKernelCompatibility() &&
544*70a7ec85SAndroid Build Coastguard Worker kernel()
545*70a7ec85SAndroid Build Coastguard Worker ->getMatchedKernelRequirements(mat.framework.mKernels, kernelTagLevel, error)
546*70a7ec85SAndroid Build Coastguard Worker .empty()) {
547*70a7ec85SAndroid Build Coastguard Worker return false;
548*70a7ec85SAndroid Build Coastguard Worker }
549*70a7ec85SAndroid Build Coastguard Worker }
550*70a7ec85SAndroid Build Coastguard Worker
551*70a7ec85SAndroid Build Coastguard Worker return true;
552*70a7ec85SAndroid Build Coastguard Worker }
553*70a7ec85SAndroid Build Coastguard Worker
shouldCheckKernelCompatibility() const554*70a7ec85SAndroid Build Coastguard Worker bool HalManifest::shouldCheckKernelCompatibility() const {
555*70a7ec85SAndroid Build Coastguard Worker return kernel().has_value() && kernel()->version() != KernelVersion{};
556*70a7ec85SAndroid Build Coastguard Worker }
557*70a7ec85SAndroid Build Coastguard Worker
generateCompatibleMatrix(bool optional) const558*70a7ec85SAndroid Build Coastguard Worker CompatibilityMatrix HalManifest::generateCompatibleMatrix(bool optional) const {
559*70a7ec85SAndroid Build Coastguard Worker CompatibilityMatrix matrix;
560*70a7ec85SAndroid Build Coastguard Worker
561*70a7ec85SAndroid Build Coastguard Worker std::set<std::tuple<HalFormat, std::string, Version, std::string, std::string>> instances;
562*70a7ec85SAndroid Build Coastguard Worker
563*70a7ec85SAndroid Build Coastguard Worker forEachInstance([&matrix, &instances, optional](const ManifestInstance& e) {
564*70a7ec85SAndroid Build Coastguard Worker auto&& [it, added] =
565*70a7ec85SAndroid Build Coastguard Worker instances.emplace(e.format(), e.package(), e.version(), e.interface(), e.instance());
566*70a7ec85SAndroid Build Coastguard Worker if (!added) {
567*70a7ec85SAndroid Build Coastguard Worker return true;
568*70a7ec85SAndroid Build Coastguard Worker }
569*70a7ec85SAndroid Build Coastguard Worker
570*70a7ec85SAndroid Build Coastguard Worker matrix.add(MatrixHal{
571*70a7ec85SAndroid Build Coastguard Worker .format = e.format(),
572*70a7ec85SAndroid Build Coastguard Worker .name = e.package(),
573*70a7ec85SAndroid Build Coastguard Worker .versionRanges = {VersionRange{e.version().majorVer, e.version().minorVer}},
574*70a7ec85SAndroid Build Coastguard Worker .optional = optional,
575*70a7ec85SAndroid Build Coastguard Worker .interfaces = {{e.interface(), HalInterface{e.interface(), {e.instance()}}}}});
576*70a7ec85SAndroid Build Coastguard Worker return true;
577*70a7ec85SAndroid Build Coastguard Worker });
578*70a7ec85SAndroid Build Coastguard Worker if (mType == SchemaType::FRAMEWORK) {
579*70a7ec85SAndroid Build Coastguard Worker matrix.mType = SchemaType::DEVICE;
580*70a7ec85SAndroid Build Coastguard Worker // VNDK does not need to be added for compatibility
581*70a7ec85SAndroid Build Coastguard Worker } else if (mType == SchemaType::DEVICE) {
582*70a7ec85SAndroid Build Coastguard Worker matrix.mType = SchemaType::FRAMEWORK;
583*70a7ec85SAndroid Build Coastguard Worker matrix.framework.mSepolicy = Sepolicy(0u /* kernelSepolicyVersion */,
584*70a7ec85SAndroid Build Coastguard Worker {{device.mSepolicyVersion.majorVer, device.mSepolicyVersion.minorVer}});
585*70a7ec85SAndroid Build Coastguard Worker }
586*70a7ec85SAndroid Build Coastguard Worker
587*70a7ec85SAndroid Build Coastguard Worker return matrix;
588*70a7ec85SAndroid Build Coastguard Worker }
589*70a7ec85SAndroid Build Coastguard Worker
fetchAllInformation(const FileSystem * fileSystem,const std::string & path,std::string * error)590*70a7ec85SAndroid Build Coastguard Worker status_t HalManifest::fetchAllInformation(const FileSystem* fileSystem, const std::string& path,
591*70a7ec85SAndroid Build Coastguard Worker std::string* error) {
592*70a7ec85SAndroid Build Coastguard Worker return details::fetchAllInformation(fileSystem, path, this, error);
593*70a7ec85SAndroid Build Coastguard Worker }
594*70a7ec85SAndroid Build Coastguard Worker
type() const595*70a7ec85SAndroid Build Coastguard Worker SchemaType HalManifest::type() const {
596*70a7ec85SAndroid Build Coastguard Worker return mType;
597*70a7ec85SAndroid Build Coastguard Worker }
598*70a7ec85SAndroid Build Coastguard Worker
setType(SchemaType type)599*70a7ec85SAndroid Build Coastguard Worker void HalManifest::setType(SchemaType type) {
600*70a7ec85SAndroid Build Coastguard Worker mType = type;
601*70a7ec85SAndroid Build Coastguard Worker }
602*70a7ec85SAndroid Build Coastguard Worker
level() const603*70a7ec85SAndroid Build Coastguard Worker Level HalManifest::level() const {
604*70a7ec85SAndroid Build Coastguard Worker return mLevel;
605*70a7ec85SAndroid Build Coastguard Worker }
606*70a7ec85SAndroid Build Coastguard Worker
sepolicyVersion() const607*70a7ec85SAndroid Build Coastguard Worker const SepolicyVersion& HalManifest::sepolicyVersion() const {
608*70a7ec85SAndroid Build Coastguard Worker CHECK(mType == SchemaType::DEVICE);
609*70a7ec85SAndroid Build Coastguard Worker return device.mSepolicyVersion;
610*70a7ec85SAndroid Build Coastguard Worker }
611*70a7ec85SAndroid Build Coastguard Worker
vendorNdks() const612*70a7ec85SAndroid Build Coastguard Worker const std::vector<VendorNdk>& HalManifest::vendorNdks() const {
613*70a7ec85SAndroid Build Coastguard Worker CHECK(mType == SchemaType::FRAMEWORK);
614*70a7ec85SAndroid Build Coastguard Worker return framework.mVendorNdks;
615*70a7ec85SAndroid Build Coastguard Worker }
616*70a7ec85SAndroid Build Coastguard Worker
getXmlFilePath(const std::string & xmlFileName,const Version & version) const617*70a7ec85SAndroid Build Coastguard Worker std::string HalManifest::getXmlFilePath(const std::string& xmlFileName,
618*70a7ec85SAndroid Build Coastguard Worker const Version& version) const {
619*70a7ec85SAndroid Build Coastguard Worker using std::literals::string_literals::operator""s;
620*70a7ec85SAndroid Build Coastguard Worker auto range = getXmlFiles(xmlFileName);
621*70a7ec85SAndroid Build Coastguard Worker for (auto it = range.first; it != range.second; ++it) {
622*70a7ec85SAndroid Build Coastguard Worker const ManifestXmlFile& manifestXmlFile = it->second;
623*70a7ec85SAndroid Build Coastguard Worker if (manifestXmlFile.version() == version) {
624*70a7ec85SAndroid Build Coastguard Worker if (!manifestXmlFile.overriddenPath().empty()) {
625*70a7ec85SAndroid Build Coastguard Worker return manifestXmlFile.overriddenPath();
626*70a7ec85SAndroid Build Coastguard Worker }
627*70a7ec85SAndroid Build Coastguard Worker return "/"s + (type() == SchemaType::DEVICE ? "vendor" : "system") + "/etc/" +
628*70a7ec85SAndroid Build Coastguard Worker xmlFileName + "_V" + std::to_string(version.majorVer) + "_" +
629*70a7ec85SAndroid Build Coastguard Worker std::to_string(version.minorVer) + ".xml";
630*70a7ec85SAndroid Build Coastguard Worker }
631*70a7ec85SAndroid Build Coastguard Worker }
632*70a7ec85SAndroid Build Coastguard Worker return "";
633*70a7ec85SAndroid Build Coastguard Worker }
634*70a7ec85SAndroid Build Coastguard Worker
operator ==(const HalManifest & lft,const HalManifest & rgt)635*70a7ec85SAndroid Build Coastguard Worker bool operator==(const HalManifest &lft, const HalManifest &rgt) {
636*70a7ec85SAndroid Build Coastguard Worker // ignore fileName().
637*70a7ec85SAndroid Build Coastguard Worker return lft.mType == rgt.mType && lft.mLevel == rgt.mLevel && lft.mHals == rgt.mHals &&
638*70a7ec85SAndroid Build Coastguard Worker lft.mXmlFiles == rgt.mXmlFiles &&
639*70a7ec85SAndroid Build Coastguard Worker (lft.mType != SchemaType::DEVICE ||
640*70a7ec85SAndroid Build Coastguard Worker (lft.device.mSepolicyVersion == rgt.device.mSepolicyVersion &&
641*70a7ec85SAndroid Build Coastguard Worker lft.device.mKernel == rgt.device.mKernel)) &&
642*70a7ec85SAndroid Build Coastguard Worker (lft.mType != SchemaType::FRAMEWORK ||
643*70a7ec85SAndroid Build Coastguard Worker (
644*70a7ec85SAndroid Build Coastguard Worker #pragma clang diagnostic push
645*70a7ec85SAndroid Build Coastguard Worker #pragma clang diagnostic ignored "-Wdeprecated-declarations"
646*70a7ec85SAndroid Build Coastguard Worker lft.framework.mVndks == rgt.framework.mVndks &&
647*70a7ec85SAndroid Build Coastguard Worker #pragma clang diagnostic pop
648*70a7ec85SAndroid Build Coastguard Worker lft.framework.mVendorNdks == rgt.framework.mVendorNdks &&
649*70a7ec85SAndroid Build Coastguard Worker lft.framework.mSystemSdk == rgt.framework.mSystemSdk));
650*70a7ec85SAndroid Build Coastguard Worker }
651*70a7ec85SAndroid Build Coastguard Worker
652*70a7ec85SAndroid Build Coastguard Worker // Alternative to forEachInstance if you just need a set of instance names instead.
getInstances(HalFormat format,ExclusiveTo exclusiveTo,const std::string & package,const Version & version,const std::string & interfaceName) const653*70a7ec85SAndroid Build Coastguard Worker std::set<std::string> HalManifest::getInstances(HalFormat format, ExclusiveTo exclusiveTo,
654*70a7ec85SAndroid Build Coastguard Worker const std::string& package, const Version& version,
655*70a7ec85SAndroid Build Coastguard Worker const std::string& interfaceName) const {
656*70a7ec85SAndroid Build Coastguard Worker std::set<std::string> ret;
657*70a7ec85SAndroid Build Coastguard Worker (void)forEachInstanceOfInterface(format, exclusiveTo, package, version, interfaceName,
658*70a7ec85SAndroid Build Coastguard Worker [&ret](const auto& e) {
659*70a7ec85SAndroid Build Coastguard Worker ret.insert(e.instance());
660*70a7ec85SAndroid Build Coastguard Worker return true;
661*70a7ec85SAndroid Build Coastguard Worker });
662*70a7ec85SAndroid Build Coastguard Worker return ret;
663*70a7ec85SAndroid Build Coastguard Worker }
664*70a7ec85SAndroid Build Coastguard Worker
665*70a7ec85SAndroid Build Coastguard Worker // Return whether instance is in getInstances(...).
hasInstance(HalFormat format,ExclusiveTo exclusiveTo,const std::string & package,const Version & version,const std::string & interfaceName,const std::string & instance) const666*70a7ec85SAndroid Build Coastguard Worker bool HalManifest::hasInstance(HalFormat format, ExclusiveTo exclusiveTo, const std::string& package,
667*70a7ec85SAndroid Build Coastguard Worker const Version& version, const std::string& interfaceName,
668*70a7ec85SAndroid Build Coastguard Worker const std::string& instance) const {
669*70a7ec85SAndroid Build Coastguard Worker bool found = false;
670*70a7ec85SAndroid Build Coastguard Worker (void)forEachInstanceOfInterface(format, exclusiveTo, package, version, interfaceName,
671*70a7ec85SAndroid Build Coastguard Worker [&found, &instance](const auto& e) {
672*70a7ec85SAndroid Build Coastguard Worker found |= (instance == e.instance());
673*70a7ec85SAndroid Build Coastguard Worker return !found; // if not found, continue
674*70a7ec85SAndroid Build Coastguard Worker });
675*70a7ec85SAndroid Build Coastguard Worker return found;
676*70a7ec85SAndroid Build Coastguard Worker }
getHidlInstances(const std::string & package,const Version & version,const std::string & interfaceName) const677*70a7ec85SAndroid Build Coastguard Worker std::set<std::string> HalManifest::getHidlInstances(const std::string& package,
678*70a7ec85SAndroid Build Coastguard Worker const Version& version,
679*70a7ec85SAndroid Build Coastguard Worker const std::string& interfaceName) const {
680*70a7ec85SAndroid Build Coastguard Worker return getInstances(HalFormat::HIDL, ExclusiveTo::EMPTY, package, version, interfaceName);
681*70a7ec85SAndroid Build Coastguard Worker }
682*70a7ec85SAndroid Build Coastguard Worker
getAidlInstances(const std::string & package,const std::string & interfaceName) const683*70a7ec85SAndroid Build Coastguard Worker std::set<std::string> HalManifest::getAidlInstances(const std::string& package,
684*70a7ec85SAndroid Build Coastguard Worker const std::string& interfaceName) const {
685*70a7ec85SAndroid Build Coastguard Worker // Only get the instances available on the host device with ExclusiveTo::EMPTY
686*70a7ec85SAndroid Build Coastguard Worker return getAidlInstances(package, 0, interfaceName);
687*70a7ec85SAndroid Build Coastguard Worker }
688*70a7ec85SAndroid Build Coastguard Worker
getAidlInstances(const std::string & package,size_t version,const std::string & interfaceName) const689*70a7ec85SAndroid Build Coastguard Worker std::set<std::string> HalManifest::getAidlInstances(const std::string& package, size_t version,
690*70a7ec85SAndroid Build Coastguard Worker const std::string& interfaceName) const {
691*70a7ec85SAndroid Build Coastguard Worker // Only get the instances available on the host device with ExclusiveTo::EMPTY
692*70a7ec85SAndroid Build Coastguard Worker return getInstances(HalFormat::AIDL, ExclusiveTo::EMPTY, package,
693*70a7ec85SAndroid Build Coastguard Worker {details::kFakeAidlMajorVersion, version}, interfaceName);
694*70a7ec85SAndroid Build Coastguard Worker }
695*70a7ec85SAndroid Build Coastguard Worker
getNativeInstances(const std::string & package) const696*70a7ec85SAndroid Build Coastguard Worker std::set<std::string> HalManifest::getNativeInstances(const std::string& package) const {
697*70a7ec85SAndroid Build Coastguard Worker std::set<std::string> instances;
698*70a7ec85SAndroid Build Coastguard Worker forEachNativeInstance(package, [&](const auto& inst) {
699*70a7ec85SAndroid Build Coastguard Worker instances.insert(inst.instance());
700*70a7ec85SAndroid Build Coastguard Worker return true;
701*70a7ec85SAndroid Build Coastguard Worker });
702*70a7ec85SAndroid Build Coastguard Worker return instances;
703*70a7ec85SAndroid Build Coastguard Worker }
704*70a7ec85SAndroid Build Coastguard Worker
hasHidlInstance(const std::string & package,const Version & version,const std::string & interfaceName,const std::string & instance) const705*70a7ec85SAndroid Build Coastguard Worker bool HalManifest::hasHidlInstance(const std::string& package, const Version& version,
706*70a7ec85SAndroid Build Coastguard Worker const std::string& interfaceName,
707*70a7ec85SAndroid Build Coastguard Worker const std::string& instance) const {
708*70a7ec85SAndroid Build Coastguard Worker return hasInstance(HalFormat::HIDL, ExclusiveTo::EMPTY, package, version, interfaceName,
709*70a7ec85SAndroid Build Coastguard Worker instance);
710*70a7ec85SAndroid Build Coastguard Worker }
711*70a7ec85SAndroid Build Coastguard Worker
hasAidlInstance(const std::string & package,const std::string & interface,const std::string & instance) const712*70a7ec85SAndroid Build Coastguard Worker bool HalManifest::hasAidlInstance(const std::string& package, const std::string& interface,
713*70a7ec85SAndroid Build Coastguard Worker const std::string& instance) const {
714*70a7ec85SAndroid Build Coastguard Worker return hasAidlInstance(package, 0, interface, instance);
715*70a7ec85SAndroid Build Coastguard Worker }
716*70a7ec85SAndroid Build Coastguard Worker
hasAidlInstance(const std::string & package,size_t version,const std::string & interface,const std::string & instance) const717*70a7ec85SAndroid Build Coastguard Worker bool HalManifest::hasAidlInstance(const std::string& package, size_t version,
718*70a7ec85SAndroid Build Coastguard Worker const std::string& interface, const std::string& instance) const {
719*70a7ec85SAndroid Build Coastguard Worker return hasInstance(HalFormat::AIDL, ExclusiveTo::EMPTY, package,
720*70a7ec85SAndroid Build Coastguard Worker {details::kFakeAidlMajorVersion, version}, interface, instance);
721*70a7ec85SAndroid Build Coastguard Worker }
722*70a7ec85SAndroid Build Coastguard Worker
hasNativeInstance(const std::string & package,const std::string & instance) const723*70a7ec85SAndroid Build Coastguard Worker bool HalManifest::hasNativeInstance(const std::string& package, const std::string& instance) const {
724*70a7ec85SAndroid Build Coastguard Worker bool found = false;
725*70a7ec85SAndroid Build Coastguard Worker forEachNativeInstance(package, [&](const auto& inst) {
726*70a7ec85SAndroid Build Coastguard Worker found |= inst.instance() == instance;
727*70a7ec85SAndroid Build Coastguard Worker return !found; // continue if not found
728*70a7ec85SAndroid Build Coastguard Worker });
729*70a7ec85SAndroid Build Coastguard Worker return found;
730*70a7ec85SAndroid Build Coastguard Worker }
731*70a7ec85SAndroid Build Coastguard Worker
insertInstance(const FqInstance & fqInstance,Transport transport,Arch arch,HalFormat format,std::string * error)732*70a7ec85SAndroid Build Coastguard Worker bool HalManifest::insertInstance(const FqInstance& fqInstance, Transport transport, Arch arch,
733*70a7ec85SAndroid Build Coastguard Worker HalFormat format, std::string* error) {
734*70a7ec85SAndroid Build Coastguard Worker for (ManifestHal& hal : getHals()) {
735*70a7ec85SAndroid Build Coastguard Worker if (hal.name == fqInstance.getPackage() && hal.format == format &&
736*70a7ec85SAndroid Build Coastguard Worker hal.transport() == transport && hal.arch() == arch) {
737*70a7ec85SAndroid Build Coastguard Worker return hal.insertInstance(fqInstance, error);
738*70a7ec85SAndroid Build Coastguard Worker }
739*70a7ec85SAndroid Build Coastguard Worker }
740*70a7ec85SAndroid Build Coastguard Worker
741*70a7ec85SAndroid Build Coastguard Worker ManifestHal hal;
742*70a7ec85SAndroid Build Coastguard Worker hal.name = fqInstance.getPackage();
743*70a7ec85SAndroid Build Coastguard Worker hal.format = format;
744*70a7ec85SAndroid Build Coastguard Worker hal.transportArch = TransportArch(transport, arch);
745*70a7ec85SAndroid Build Coastguard Worker if (!hal.insertInstance(fqInstance, error)) return false;
746*70a7ec85SAndroid Build Coastguard Worker return add(std::move(hal), error);
747*70a7ec85SAndroid Build Coastguard Worker }
748*70a7ec85SAndroid Build Coastguard Worker
empty() const749*70a7ec85SAndroid Build Coastguard Worker bool HalManifest::empty() const {
750*70a7ec85SAndroid Build Coastguard Worker HalManifest emptyManifest;
751*70a7ec85SAndroid Build Coastguard Worker emptyManifest.setType(type());
752*70a7ec85SAndroid Build Coastguard Worker return (*this) == emptyManifest;
753*70a7ec85SAndroid Build Coastguard Worker }
754*70a7ec85SAndroid Build Coastguard Worker
kernel() const755*70a7ec85SAndroid Build Coastguard Worker const std::optional<KernelInfo>& HalManifest::kernel() const {
756*70a7ec85SAndroid Build Coastguard Worker return device.mKernel;
757*70a7ec85SAndroid Build Coastguard Worker }
758*70a7ec85SAndroid Build Coastguard Worker
mergeKernel(std::optional<KernelInfo> * other,std::string * error)759*70a7ec85SAndroid Build Coastguard Worker bool HalManifest::mergeKernel(std::optional<KernelInfo>* other, std::string* error) {
760*70a7ec85SAndroid Build Coastguard Worker if (!other->has_value()) {
761*70a7ec85SAndroid Build Coastguard Worker return true;
762*70a7ec85SAndroid Build Coastguard Worker }
763*70a7ec85SAndroid Build Coastguard Worker
764*70a7ec85SAndroid Build Coastguard Worker if (device.mKernel.has_value()) {
765*70a7ec85SAndroid Build Coastguard Worker if (!device.mKernel->merge(&**other, error)) {
766*70a7ec85SAndroid Build Coastguard Worker return false;
767*70a7ec85SAndroid Build Coastguard Worker }
768*70a7ec85SAndroid Build Coastguard Worker } else {
769*70a7ec85SAndroid Build Coastguard Worker device.mKernel = std::move(*other);
770*70a7ec85SAndroid Build Coastguard Worker }
771*70a7ec85SAndroid Build Coastguard Worker
772*70a7ec85SAndroid Build Coastguard Worker *other = std::nullopt;
773*70a7ec85SAndroid Build Coastguard Worker return true;
774*70a7ec85SAndroid Build Coastguard Worker }
775*70a7ec85SAndroid Build Coastguard Worker
addAll(HalManifest * other,std::string * error)776*70a7ec85SAndroid Build Coastguard Worker bool HalManifest::addAll(HalManifest* other, std::string* error) {
777*70a7ec85SAndroid Build Coastguard Worker if (type() != other->type()) {
778*70a7ec85SAndroid Build Coastguard Worker if (error) {
779*70a7ec85SAndroid Build Coastguard Worker *error = "Cannot add a " + to_string(other->type()) + " manifest to a " +
780*70a7ec85SAndroid Build Coastguard Worker to_string(type()) + " manifest";
781*70a7ec85SAndroid Build Coastguard Worker }
782*70a7ec85SAndroid Build Coastguard Worker return false;
783*70a7ec85SAndroid Build Coastguard Worker }
784*70a7ec85SAndroid Build Coastguard Worker
785*70a7ec85SAndroid Build Coastguard Worker if (!addAllHals(other, error)) {
786*70a7ec85SAndroid Build Coastguard Worker return false;
787*70a7ec85SAndroid Build Coastguard Worker }
788*70a7ec85SAndroid Build Coastguard Worker
789*70a7ec85SAndroid Build Coastguard Worker if (!addAllXmlFiles(other, error)) {
790*70a7ec85SAndroid Build Coastguard Worker return false;
791*70a7ec85SAndroid Build Coastguard Worker }
792*70a7ec85SAndroid Build Coastguard Worker
793*70a7ec85SAndroid Build Coastguard Worker if (!mergeField(&mLevel, &other->mLevel, Level::UNSPECIFIED)) {
794*70a7ec85SAndroid Build Coastguard Worker if (error) {
795*70a7ec85SAndroid Build Coastguard Worker *error = "Conflicting target-level: " + to_string(level()) + " vs. " +
796*70a7ec85SAndroid Build Coastguard Worker to_string(other->level());
797*70a7ec85SAndroid Build Coastguard Worker }
798*70a7ec85SAndroid Build Coastguard Worker return false;
799*70a7ec85SAndroid Build Coastguard Worker }
800*70a7ec85SAndroid Build Coastguard Worker
801*70a7ec85SAndroid Build Coastguard Worker if (type() == SchemaType::DEVICE) {
802*70a7ec85SAndroid Build Coastguard Worker if (!mergeField(&device.mSepolicyVersion, &other->device.mSepolicyVersion)) {
803*70a7ec85SAndroid Build Coastguard Worker if (error) {
804*70a7ec85SAndroid Build Coastguard Worker *error = "Conflicting sepolicy version: " + to_string(sepolicyVersion()) + " vs. " +
805*70a7ec85SAndroid Build Coastguard Worker to_string(other->sepolicyVersion());
806*70a7ec85SAndroid Build Coastguard Worker }
807*70a7ec85SAndroid Build Coastguard Worker return false;
808*70a7ec85SAndroid Build Coastguard Worker }
809*70a7ec85SAndroid Build Coastguard Worker
810*70a7ec85SAndroid Build Coastguard Worker if (!mergeKernel(&other->device.mKernel, error)) {
811*70a7ec85SAndroid Build Coastguard Worker return false;
812*70a7ec85SAndroid Build Coastguard Worker }
813*70a7ec85SAndroid Build Coastguard Worker } else if (type() == SchemaType::FRAMEWORK) {
814*70a7ec85SAndroid Build Coastguard Worker #pragma clang diagnostic push
815*70a7ec85SAndroid Build Coastguard Worker #pragma clang diagnostic ignored "-Wdeprecated-declarations"
816*70a7ec85SAndroid Build Coastguard Worker framework.mVndks.insert(framework.mVndks.end(), other->framework.mVndks.begin(),
817*70a7ec85SAndroid Build Coastguard Worker other->framework.mVndks.end());
818*70a7ec85SAndroid Build Coastguard Worker other->framework.mVndks.clear();
819*70a7ec85SAndroid Build Coastguard Worker #pragma clang diagnostic pop
820*70a7ec85SAndroid Build Coastguard Worker
821*70a7ec85SAndroid Build Coastguard Worker framework.mVendorNdks.insert(framework.mVendorNdks.end(),
822*70a7ec85SAndroid Build Coastguard Worker other->framework.mVendorNdks.begin(),
823*70a7ec85SAndroid Build Coastguard Worker other->framework.mVendorNdks.end());
824*70a7ec85SAndroid Build Coastguard Worker other->framework.mVendorNdks.clear();
825*70a7ec85SAndroid Build Coastguard Worker
826*70a7ec85SAndroid Build Coastguard Worker framework.mSystemSdk.addAll(&other->framework.mSystemSdk);
827*70a7ec85SAndroid Build Coastguard Worker } else {
828*70a7ec85SAndroid Build Coastguard Worker LOG(FATAL) << "unknown SchemaType: "
829*70a7ec85SAndroid Build Coastguard Worker << static_cast<std::underlying_type_t<SchemaType>>(type());
830*70a7ec85SAndroid Build Coastguard Worker }
831*70a7ec85SAndroid Build Coastguard Worker
832*70a7ec85SAndroid Build Coastguard Worker if (!other->empty()) {
833*70a7ec85SAndroid Build Coastguard Worker if (error) {
834*70a7ec85SAndroid Build Coastguard Worker *error =
835*70a7ec85SAndroid Build Coastguard Worker "Cannot add another manifest because it contains extraneous entries that "
836*70a7ec85SAndroid Build Coastguard Worker "are not recognized.";
837*70a7ec85SAndroid Build Coastguard Worker }
838*70a7ec85SAndroid Build Coastguard Worker return false;
839*70a7ec85SAndroid Build Coastguard Worker }
840*70a7ec85SAndroid Build Coastguard Worker
841*70a7ec85SAndroid Build Coastguard Worker return true;
842*70a7ec85SAndroid Build Coastguard Worker }
843*70a7ec85SAndroid Build Coastguard Worker
inferredKernelLevel() const844*70a7ec85SAndroid Build Coastguard Worker Level HalManifest::inferredKernelLevel() const {
845*70a7ec85SAndroid Build Coastguard Worker if (kernel().has_value()) {
846*70a7ec85SAndroid Build Coastguard Worker if (kernel()->level() != Level::UNSPECIFIED) {
847*70a7ec85SAndroid Build Coastguard Worker return kernel()->level();
848*70a7ec85SAndroid Build Coastguard Worker }
849*70a7ec85SAndroid Build Coastguard Worker }
850*70a7ec85SAndroid Build Coastguard Worker // As a special case, for devices launching with R and above, also infer from <manifest>.level.
851*70a7ec85SAndroid Build Coastguard Worker // Devices launching before R may leave kernel level unspecified to use legacy kernel
852*70a7ec85SAndroid Build Coastguard Worker // matching behavior; see KernelInfo::getMatchedKernelRequirements.
853*70a7ec85SAndroid Build Coastguard Worker if (level() >= Level::R) {
854*70a7ec85SAndroid Build Coastguard Worker return level();
855*70a7ec85SAndroid Build Coastguard Worker }
856*70a7ec85SAndroid Build Coastguard Worker return Level::UNSPECIFIED;
857*70a7ec85SAndroid Build Coastguard Worker }
858*70a7ec85SAndroid Build Coastguard Worker
859*70a7ec85SAndroid Build Coastguard Worker } // namespace vintf
860*70a7ec85SAndroid Build Coastguard Worker } // namespace android
861