xref: /aosp_15_r20/system/libvintf/KernelInfo.cpp (revision 70a7ec852fcefd15a4fb57f8f183a8b1c3aacb08)
1*70a7ec85SAndroid Build Coastguard Worker /*
2*70a7ec85SAndroid Build Coastguard Worker  * Copyright (C) 2019 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 #include "KernelInfo.h"
17*70a7ec85SAndroid Build Coastguard Worker 
18*70a7ec85SAndroid Build Coastguard Worker #include "parse_string.h"
19*70a7ec85SAndroid Build Coastguard Worker #include "parse_xml.h"
20*70a7ec85SAndroid Build Coastguard Worker #include "parse_xml_internal.h"
21*70a7ec85SAndroid Build Coastguard Worker #include "utils.h"
22*70a7ec85SAndroid Build Coastguard Worker 
23*70a7ec85SAndroid Build Coastguard Worker namespace android {
24*70a7ec85SAndroid Build Coastguard Worker namespace vintf {
25*70a7ec85SAndroid Build Coastguard Worker 
26*70a7ec85SAndroid Build Coastguard Worker using details::mergeField;
27*70a7ec85SAndroid Build Coastguard Worker 
version() const28*70a7ec85SAndroid Build Coastguard Worker const KernelVersion& KernelInfo::version() const {
29*70a7ec85SAndroid Build Coastguard Worker     return mVersion;
30*70a7ec85SAndroid Build Coastguard Worker }
31*70a7ec85SAndroid Build Coastguard Worker 
configs() const32*70a7ec85SAndroid Build Coastguard Worker const std::map<std::string, std::string>& KernelInfo::configs() const {
33*70a7ec85SAndroid Build Coastguard Worker     return mConfigs;
34*70a7ec85SAndroid Build Coastguard Worker }
35*70a7ec85SAndroid Build Coastguard Worker 
level() const36*70a7ec85SAndroid Build Coastguard Worker Level KernelInfo::level() const {
37*70a7ec85SAndroid Build Coastguard Worker     return mLevel;
38*70a7ec85SAndroid Build Coastguard Worker }
39*70a7ec85SAndroid Build Coastguard Worker 
matchKernelConfigs(const std::vector<KernelConfig> & matrixConfigs,std::string * error) const40*70a7ec85SAndroid Build Coastguard Worker bool KernelInfo::matchKernelConfigs(const std::vector<KernelConfig>& matrixConfigs,
41*70a7ec85SAndroid Build Coastguard Worker                                     std::string* error) const {
42*70a7ec85SAndroid Build Coastguard Worker     std::stringstream ss;
43*70a7ec85SAndroid Build Coastguard Worker     ss << "Kernel config errors:";
44*70a7ec85SAndroid Build Coastguard Worker     bool configMatches = true;
45*70a7ec85SAndroid Build Coastguard Worker     for (const KernelConfig& matrixConfig : matrixConfigs) {
46*70a7ec85SAndroid Build Coastguard Worker         const std::string& key = matrixConfig.first;
47*70a7ec85SAndroid Build Coastguard Worker         auto it = this->mConfigs.find(key);
48*70a7ec85SAndroid Build Coastguard Worker         if (it == this->mConfigs.end()) {
49*70a7ec85SAndroid Build Coastguard Worker             // special case: <value type="tristate">n</value> matches if the config doesn't exist.
50*70a7ec85SAndroid Build Coastguard Worker             if (matrixConfig.second == KernelConfigTypedValue::gMissingConfig) {
51*70a7ec85SAndroid Build Coastguard Worker                 continue;
52*70a7ec85SAndroid Build Coastguard Worker             }
53*70a7ec85SAndroid Build Coastguard Worker             ss << "\n    Missing config " << key;
54*70a7ec85SAndroid Build Coastguard Worker             configMatches = false;
55*70a7ec85SAndroid Build Coastguard Worker             continue;
56*70a7ec85SAndroid Build Coastguard Worker         }
57*70a7ec85SAndroid Build Coastguard Worker         const std::string& kernelValue = it->second;
58*70a7ec85SAndroid Build Coastguard Worker         if (!matrixConfig.second.matchValue(kernelValue)) {
59*70a7ec85SAndroid Build Coastguard Worker             ss << "\n    For config " << key << ", value = " << kernelValue << " but required "
60*70a7ec85SAndroid Build Coastguard Worker                << to_string(matrixConfig.second);
61*70a7ec85SAndroid Build Coastguard Worker             configMatches = false;
62*70a7ec85SAndroid Build Coastguard Worker             continue;
63*70a7ec85SAndroid Build Coastguard Worker         }
64*70a7ec85SAndroid Build Coastguard Worker     }
65*70a7ec85SAndroid Build Coastguard Worker     if (!configMatches && error != nullptr) {
66*70a7ec85SAndroid Build Coastguard Worker         *error = ss.str();
67*70a7ec85SAndroid Build Coastguard Worker     }
68*70a7ec85SAndroid Build Coastguard Worker     return configMatches;
69*70a7ec85SAndroid Build Coastguard Worker }
70*70a7ec85SAndroid Build Coastguard Worker 
matchKernelVersion(const KernelVersion & minLts) const71*70a7ec85SAndroid Build Coastguard Worker bool KernelInfo::matchKernelVersion(const KernelVersion& minLts) const {
72*70a7ec85SAndroid Build Coastguard Worker     return mVersion.dropMinor() == minLts.dropMinor() && minLts.minorRev <= mVersion.minorRev;
73*70a7ec85SAndroid Build Coastguard Worker }
74*70a7ec85SAndroid Build Coastguard Worker 
getMatchedKernelRequirements(const std::vector<MatrixKernel> & kernels,Level kernelLevel,std::string * error) const75*70a7ec85SAndroid Build Coastguard Worker std::vector<const MatrixKernel*> KernelInfo::getMatchedKernelRequirements(
76*70a7ec85SAndroid Build Coastguard Worker     const std::vector<MatrixKernel>& kernels, Level kernelLevel, std::string* error) const {
77*70a7ec85SAndroid Build Coastguard Worker     std::map<Level, std::vector<const MatrixKernel*>> kernelsForLevel;
78*70a7ec85SAndroid Build Coastguard Worker     for (const MatrixKernel& matrixKernel : kernels) {
79*70a7ec85SAndroid Build Coastguard Worker         const auto& minLts = matrixKernel.minLts();
80*70a7ec85SAndroid Build Coastguard Worker         auto matrixKernelLevel = matrixKernel.getSourceMatrixLevel();
81*70a7ec85SAndroid Build Coastguard Worker 
82*70a7ec85SAndroid Build Coastguard Worker         // Filter out kernels with different x.y.
83*70a7ec85SAndroid Build Coastguard Worker         if (mVersion.dropMinor() != minLts.dropMinor()) {
84*70a7ec85SAndroid Build Coastguard Worker             continue;
85*70a7ec85SAndroid Build Coastguard Worker         }
86*70a7ec85SAndroid Build Coastguard Worker 
87*70a7ec85SAndroid Build Coastguard Worker         // Check matrix kernel level
88*70a7ec85SAndroid Build Coastguard Worker 
89*70a7ec85SAndroid Build Coastguard Worker         // Use legacy behavior when kernel FCM version is not specified. Blindly add all of them
90*70a7ec85SAndroid Build Coastguard Worker         // here. The correct one (with smallest matrixKernelLevel) will be picked later.
91*70a7ec85SAndroid Build Coastguard Worker         if (kernelLevel == Level::UNSPECIFIED) {
92*70a7ec85SAndroid Build Coastguard Worker             kernelsForLevel[matrixKernelLevel].push_back(&matrixKernel);
93*70a7ec85SAndroid Build Coastguard Worker             continue;
94*70a7ec85SAndroid Build Coastguard Worker         }
95*70a7ec85SAndroid Build Coastguard Worker 
96*70a7ec85SAndroid Build Coastguard Worker         if (matrixKernelLevel == Level::UNSPECIFIED) {
97*70a7ec85SAndroid Build Coastguard Worker             if (error) {
98*70a7ec85SAndroid Build Coastguard Worker                 *error = "Seen unspecified source matrix level; this should not happen.";
99*70a7ec85SAndroid Build Coastguard Worker             }
100*70a7ec85SAndroid Build Coastguard Worker             return {};
101*70a7ec85SAndroid Build Coastguard Worker         }
102*70a7ec85SAndroid Build Coastguard Worker 
103*70a7ec85SAndroid Build Coastguard Worker         if (matrixKernelLevel < kernelLevel) {
104*70a7ec85SAndroid Build Coastguard Worker             continue;
105*70a7ec85SAndroid Build Coastguard Worker         }
106*70a7ec85SAndroid Build Coastguard Worker 
107*70a7ec85SAndroid Build Coastguard Worker         // matrix level >= kernel level
108*70a7ec85SAndroid Build Coastguard Worker 
109*70a7ec85SAndroid Build Coastguard Worker         // for kernel level >= S, do not allow matrix level > kernel level; i.e. only check
110*70a7ec85SAndroid Build Coastguard Worker         // matching KMI.
111*70a7ec85SAndroid Build Coastguard Worker         if (kernelLevel >= Level::S && matrixKernelLevel > kernelLevel) {
112*70a7ec85SAndroid Build Coastguard Worker             continue;
113*70a7ec85SAndroid Build Coastguard Worker         }
114*70a7ec85SAndroid Build Coastguard Worker 
115*70a7ec85SAndroid Build Coastguard Worker         kernelsForLevel[matrixKernelLevel].push_back(&matrixKernel);
116*70a7ec85SAndroid Build Coastguard Worker     }
117*70a7ec85SAndroid Build Coastguard Worker 
118*70a7ec85SAndroid Build Coastguard Worker     if (kernelsForLevel.empty()) {
119*70a7ec85SAndroid Build Coastguard Worker         if (error) {
120*70a7ec85SAndroid Build Coastguard Worker             std::stringstream ss;
121*70a7ec85SAndroid Build Coastguard Worker             ss << "No kernel entry found for kernel version " << mVersion.dropMinor()
122*70a7ec85SAndroid Build Coastguard Worker                << " at kernel FCM version "
123*70a7ec85SAndroid Build Coastguard Worker                << (kernelLevel == Level::UNSPECIFIED ? "unspecified" : to_string(kernelLevel))
124*70a7ec85SAndroid Build Coastguard Worker                << ". The following kernel requirements are checked:";
125*70a7ec85SAndroid Build Coastguard Worker             for (const MatrixKernel& matrixKernel : kernels) {
126*70a7ec85SAndroid Build Coastguard Worker                 ss << "\n  Minimum LTS: " << matrixKernel.minLts()
127*70a7ec85SAndroid Build Coastguard Worker                    << ", kernel FCM version: " << matrixKernel.getSourceMatrixLevel()
128*70a7ec85SAndroid Build Coastguard Worker                    << (matrixKernel.conditions().empty() ? "" : ", with conditionals");
129*70a7ec85SAndroid Build Coastguard Worker             };
130*70a7ec85SAndroid Build Coastguard Worker             *error = ss.str();
131*70a7ec85SAndroid Build Coastguard Worker         }
132*70a7ec85SAndroid Build Coastguard Worker         return {};
133*70a7ec85SAndroid Build Coastguard Worker     }
134*70a7ec85SAndroid Build Coastguard Worker 
135*70a7ec85SAndroid Build Coastguard Worker     // At this point, kernelsForLevel contains kernel requirements for each level.
136*70a7ec85SAndroid Build Coastguard Worker     // For example, if the running kernel version is 4.14.y then kernelsForLevel contains
137*70a7ec85SAndroid Build Coastguard Worker     // 4.14-p, 4.14-q, 4.14-r.
138*70a7ec85SAndroid Build Coastguard Worker     // (This excludes kernels < kernel FCM version, or device FCM version if kernel FCM version is
139*70a7ec85SAndroid Build Coastguard Worker     // empty. For example, if device level = Q and kernel level is unspecified, this list only
140*70a7ec85SAndroid Build Coastguard Worker     // contains 4.14-q and 4.14-r).
141*70a7ec85SAndroid Build Coastguard Worker 
142*70a7ec85SAndroid Build Coastguard Worker     // Use legacy behavior when kernel FCM version is not specified. e.g. target FCM version 3 (P)
143*70a7ec85SAndroid Build Coastguard Worker     // matches kernel 4.4-p, 4.9-p, 4.14-p, 4.19-q, etc., but not 4.9-q or 4.14-q.
144*70a7ec85SAndroid Build Coastguard Worker     // Since we already filtered |kernels| based on kernel version, we only need to check the first
145*70a7ec85SAndroid Build Coastguard Worker     // item in kernelsForLevel.
146*70a7ec85SAndroid Build Coastguard Worker     // Note that this excludes *-r and above kernels. Devices with target FCM version >= 5 (R) must
147*70a7ec85SAndroid Build Coastguard Worker     // state kernel FCM version explicitly in the device manifest. The value is automatically
148*70a7ec85SAndroid Build Coastguard Worker     // inserted for devices with target FCM version >= 5 when manifest is built with assemble_vintf.
149*70a7ec85SAndroid Build Coastguard Worker     if (kernelLevel == Level::UNSPECIFIED) {
150*70a7ec85SAndroid Build Coastguard Worker         auto [matrixKernelLevel, matrixKernels] = *kernelsForLevel.begin();
151*70a7ec85SAndroid Build Coastguard Worker 
152*70a7ec85SAndroid Build Coastguard Worker         // Do not allow *-r and above kernels.
153*70a7ec85SAndroid Build Coastguard Worker         if (matrixKernelLevel != Level::UNSPECIFIED && matrixKernelLevel >= Level::R) {
154*70a7ec85SAndroid Build Coastguard Worker             if (error) {
155*70a7ec85SAndroid Build Coastguard Worker                 KernelInfo msg;
156*70a7ec85SAndroid Build Coastguard Worker                 msg.mLevel = Level::R;
157*70a7ec85SAndroid Build Coastguard Worker                 *error = "Kernel FCM version is not specified, but kernel version " +
158*70a7ec85SAndroid Build Coastguard Worker                          to_string(mVersion) +
159*70a7ec85SAndroid Build Coastguard Worker                          " is found. Fix by specifying kernel FCM version in device manifest. "
160*70a7ec85SAndroid Build Coastguard Worker                          "For example, for a *-r kernel:\n" +
161*70a7ec85SAndroid Build Coastguard Worker                          toXml(msg);
162*70a7ec85SAndroid Build Coastguard Worker             }
163*70a7ec85SAndroid Build Coastguard Worker             return {};
164*70a7ec85SAndroid Build Coastguard Worker         }
165*70a7ec85SAndroid Build Coastguard Worker 
166*70a7ec85SAndroid Build Coastguard Worker         auto matchedMatrixKernels = getMatchedKernelVersionAndConfigs(matrixKernels, error);
167*70a7ec85SAndroid Build Coastguard Worker         if (matchedMatrixKernels.empty()) {
168*70a7ec85SAndroid Build Coastguard Worker             return {};
169*70a7ec85SAndroid Build Coastguard Worker         }
170*70a7ec85SAndroid Build Coastguard Worker         return matchedMatrixKernels;
171*70a7ec85SAndroid Build Coastguard Worker     }
172*70a7ec85SAndroid Build Coastguard Worker 
173*70a7ec85SAndroid Build Coastguard Worker     // Use new behavior when kernel FCM version is specified. e.g. kernel FCM version 3 (P)
174*70a7ec85SAndroid Build Coastguard Worker     // matches kernel 4.4-p, 4.9-p, 4.14-p, 4.9-q, 4.14-q, 4.14-r etc., but not 5.4-r.
175*70a7ec85SAndroid Build Coastguard Worker     // For kernel FCM version >= S, only matching KMI is accepted. e.g. kernel FCM version 6 (S)
176*70a7ec85SAndroid Build Coastguard Worker     // matches 4.19-stable, 5.10-android12, 5.4-android12, not x.y-android13.
177*70a7ec85SAndroid Build Coastguard Worker     // Note we already filtered |kernels| based on kernel version.
178*70a7ec85SAndroid Build Coastguard Worker     auto [firstMatrixKernelLevel, firstMatrixKernels] = *kernelsForLevel.begin();
179*70a7ec85SAndroid Build Coastguard Worker     if (firstMatrixKernelLevel == Level::UNSPECIFIED || firstMatrixKernelLevel > kernelLevel) {
180*70a7ec85SAndroid Build Coastguard Worker         if (error) {
181*70a7ec85SAndroid Build Coastguard Worker             *error = "Kernel FCM Version is " + to_string(kernelLevel) + " and kernel version is " +
182*70a7ec85SAndroid Build Coastguard Worker                      to_string(mVersion) +
183*70a7ec85SAndroid Build Coastguard Worker                      ", but the first kernel FCM version allowed for kernel version " +
184*70a7ec85SAndroid Build Coastguard Worker                      to_string(mVersion.dropMinor()) + ".y is " + to_string(firstMatrixKernelLevel);
185*70a7ec85SAndroid Build Coastguard Worker         }
186*70a7ec85SAndroid Build Coastguard Worker         return {};
187*70a7ec85SAndroid Build Coastguard Worker     }
188*70a7ec85SAndroid Build Coastguard Worker     for (auto [matrixKernelLevel, matrixKernels] : kernelsForLevel) {
189*70a7ec85SAndroid Build Coastguard Worker         if (matrixKernelLevel == Level::UNSPECIFIED || matrixKernelLevel < kernelLevel) {
190*70a7ec85SAndroid Build Coastguard Worker             continue;
191*70a7ec85SAndroid Build Coastguard Worker         }
192*70a7ec85SAndroid Build Coastguard Worker         std::string errorForLevel;
193*70a7ec85SAndroid Build Coastguard Worker         auto matchedMatrixKernels =
194*70a7ec85SAndroid Build Coastguard Worker             getMatchedKernelVersionAndConfigs(matrixKernels, &errorForLevel);
195*70a7ec85SAndroid Build Coastguard Worker         if (matchedMatrixKernels.empty()) {
196*70a7ec85SAndroid Build Coastguard Worker             if (error) {
197*70a7ec85SAndroid Build Coastguard Worker                 *error += "For kernel requirements at matrix level " +
198*70a7ec85SAndroid Build Coastguard Worker                           to_string(matrixKernelLevel) + ", " + errorForLevel + "\n";
199*70a7ec85SAndroid Build Coastguard Worker             }
200*70a7ec85SAndroid Build Coastguard Worker             continue;
201*70a7ec85SAndroid Build Coastguard Worker         }
202*70a7ec85SAndroid Build Coastguard Worker         return matchedMatrixKernels;
203*70a7ec85SAndroid Build Coastguard Worker     }
204*70a7ec85SAndroid Build Coastguard Worker 
205*70a7ec85SAndroid Build Coastguard Worker     if (error) {
206*70a7ec85SAndroid Build Coastguard Worker         error->insert(0, "No compatible kernel requirement found (kernel FCM version = " +
207*70a7ec85SAndroid Build Coastguard Worker                              to_string(kernelLevel) + ").\n");
208*70a7ec85SAndroid Build Coastguard Worker     }
209*70a7ec85SAndroid Build Coastguard Worker     return {};
210*70a7ec85SAndroid Build Coastguard Worker }
211*70a7ec85SAndroid Build Coastguard Worker 
getMatchedKernelVersionAndConfigs(const std::vector<const MatrixKernel * > & kernels,std::string * error) const212*70a7ec85SAndroid Build Coastguard Worker std::vector<const MatrixKernel*> KernelInfo::getMatchedKernelVersionAndConfigs(
213*70a7ec85SAndroid Build Coastguard Worker     const std::vector<const MatrixKernel*>& kernels, std::string* error) const {
214*70a7ec85SAndroid Build Coastguard Worker     std::vector<const MatrixKernel*> result;
215*70a7ec85SAndroid Build Coastguard Worker     bool foundMatchedKernelVersion = false;
216*70a7ec85SAndroid Build Coastguard Worker     for (const MatrixKernel* matrixKernel : kernels) {
217*70a7ec85SAndroid Build Coastguard Worker         if (!matchKernelVersion(matrixKernel->minLts())) {
218*70a7ec85SAndroid Build Coastguard Worker             continue;
219*70a7ec85SAndroid Build Coastguard Worker         }
220*70a7ec85SAndroid Build Coastguard Worker         foundMatchedKernelVersion = true;
221*70a7ec85SAndroid Build Coastguard Worker         // ignore this fragment if not all conditions are met.
222*70a7ec85SAndroid Build Coastguard Worker         if (!matchKernelConfigs(matrixKernel->conditions(), nullptr)) {
223*70a7ec85SAndroid Build Coastguard Worker             continue;
224*70a7ec85SAndroid Build Coastguard Worker         }
225*70a7ec85SAndroid Build Coastguard Worker         if (!matchKernelConfigs(matrixKernel->configs(), error)) {
226*70a7ec85SAndroid Build Coastguard Worker             return {};
227*70a7ec85SAndroid Build Coastguard Worker         }
228*70a7ec85SAndroid Build Coastguard Worker         result.push_back(matrixKernel);
229*70a7ec85SAndroid Build Coastguard Worker     }
230*70a7ec85SAndroid Build Coastguard Worker     if (!foundMatchedKernelVersion) {
231*70a7ec85SAndroid Build Coastguard Worker         if (error != nullptr) {
232*70a7ec85SAndroid Build Coastguard Worker             std::stringstream ss;
233*70a7ec85SAndroid Build Coastguard Worker             ss << "Framework is incompatible with kernel version " << version()
234*70a7ec85SAndroid Build Coastguard Worker                << ", compatible kernel versions are:";
235*70a7ec85SAndroid Build Coastguard Worker             for (const MatrixKernel* matrixKernel : kernels) {
236*70a7ec85SAndroid Build Coastguard Worker                 ss << "\n  Minimum LTS: " << matrixKernel->minLts()
237*70a7ec85SAndroid Build Coastguard Worker                    << ", kernel FCM version: " << matrixKernel->getSourceMatrixLevel()
238*70a7ec85SAndroid Build Coastguard Worker                    << (matrixKernel->conditions().empty() ? "" : ", with conditionals");
239*70a7ec85SAndroid Build Coastguard Worker             };
240*70a7ec85SAndroid Build Coastguard Worker             *error = ss.str();
241*70a7ec85SAndroid Build Coastguard Worker         }
242*70a7ec85SAndroid Build Coastguard Worker         return {};
243*70a7ec85SAndroid Build Coastguard Worker     }
244*70a7ec85SAndroid Build Coastguard Worker     if (result.empty()) {
245*70a7ec85SAndroid Build Coastguard Worker         // This means matchKernelVersion passes but all matchKernelConfigs(conditions) fails.
246*70a7ec85SAndroid Build Coastguard Worker         // This should not happen because first <conditions> for each <kernel> must be
247*70a7ec85SAndroid Build Coastguard Worker         // empty. Reject here for inconsistency.
248*70a7ec85SAndroid Build Coastguard Worker         if (error != nullptr) {
249*70a7ec85SAndroid Build Coastguard Worker             error->insert(0, "Framework matches kernel version with unmet conditions.");
250*70a7ec85SAndroid Build Coastguard Worker         }
251*70a7ec85SAndroid Build Coastguard Worker         return {};
252*70a7ec85SAndroid Build Coastguard Worker     }
253*70a7ec85SAndroid Build Coastguard Worker     if (error != nullptr) {
254*70a7ec85SAndroid Build Coastguard Worker         error->clear();
255*70a7ec85SAndroid Build Coastguard Worker     }
256*70a7ec85SAndroid Build Coastguard Worker     return result;
257*70a7ec85SAndroid Build Coastguard Worker }
258*70a7ec85SAndroid Build Coastguard Worker 
operator ==(const KernelInfo & other) const259*70a7ec85SAndroid Build Coastguard Worker bool KernelInfo::operator==(const KernelInfo& other) const {
260*70a7ec85SAndroid Build Coastguard Worker     return mVersion == other.mVersion && mConfigs == other.mConfigs;
261*70a7ec85SAndroid Build Coastguard Worker }
262*70a7ec85SAndroid Build Coastguard Worker 
merge(KernelInfo * other,std::string * error)263*70a7ec85SAndroid Build Coastguard Worker bool KernelInfo::merge(KernelInfo* other, std::string* error) {
264*70a7ec85SAndroid Build Coastguard Worker     if (!mergeField(&mVersion, &other->mVersion)) {
265*70a7ec85SAndroid Build Coastguard Worker         if (error) {
266*70a7ec85SAndroid Build Coastguard Worker             *error = "Conflicting kernel version: " + to_string(version()) + " vs. " +
267*70a7ec85SAndroid Build Coastguard Worker                      to_string(other->version());
268*70a7ec85SAndroid Build Coastguard Worker         }
269*70a7ec85SAndroid Build Coastguard Worker         return false;
270*70a7ec85SAndroid Build Coastguard Worker     }
271*70a7ec85SAndroid Build Coastguard Worker 
272*70a7ec85SAndroid Build Coastguard Worker     // Do not allow merging configs. One of them must be empty.
273*70a7ec85SAndroid Build Coastguard Worker     if (!mergeField(&mConfigs, &other->mConfigs)) {
274*70a7ec85SAndroid Build Coastguard Worker         if (error) {
275*70a7ec85SAndroid Build Coastguard Worker             *error = "Found <kernel><config> items in two manifests.";
276*70a7ec85SAndroid Build Coastguard Worker         }
277*70a7ec85SAndroid Build Coastguard Worker         return false;
278*70a7ec85SAndroid Build Coastguard Worker     }
279*70a7ec85SAndroid Build Coastguard Worker 
280*70a7ec85SAndroid Build Coastguard Worker     if (!mergeField(&mLevel, &other->mLevel, Level::UNSPECIFIED)) {
281*70a7ec85SAndroid Build Coastguard Worker         if (error) {
282*70a7ec85SAndroid Build Coastguard Worker             *error = "Conflicting kernel level: " + to_string(level()) + " vs. " +
283*70a7ec85SAndroid Build Coastguard Worker                      to_string(other->level());
284*70a7ec85SAndroid Build Coastguard Worker         }
285*70a7ec85SAndroid Build Coastguard Worker         return false;
286*70a7ec85SAndroid Build Coastguard Worker     }
287*70a7ec85SAndroid Build Coastguard Worker     return true;
288*70a7ec85SAndroid Build Coastguard Worker }
289*70a7ec85SAndroid Build Coastguard Worker 
290*70a7ec85SAndroid Build Coastguard Worker }  // namespace vintf
291*70a7ec85SAndroid Build Coastguard Worker }  // namespace android
292