xref: /aosp_15_r20/system/libvintf/HalManifest.cpp (revision 70a7ec852fcefd15a4fb57f8f183a8b1c3aacb08)
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