1 /*
2 * Copyright (C) 2019 The Android Open Source Project
3 *
4 * Licensed under the Apache License, Version 2.0 (the "License");
5 * you may not use this file except in compliance with the License.
6 * You may obtain a copy of the License at
7 *
8 * http://www.apache.org/licenses/LICENSE-2.0
9 *
10 * Unless required by applicable law or agreed to in writing, software
11 * distributed under the License is distributed on an "AS IS" BASIS,
12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 * See the License for the specific language governing permissions and
14 * limitations under the License.
15 */
16 #include "KernelInfo.h"
17
18 #include "parse_string.h"
19
20 namespace android {
21 namespace vintf {
22
version() const23 const KernelVersion& KernelInfo::version() const {
24 return mVersion;
25 }
26
configs() const27 const std::map<std::string, std::string>& KernelInfo::configs() const {
28 return mConfigs;
29 }
30
matchKernelConfigs(const std::vector<KernelConfig> & matrixConfigs,std::string * error) const31 bool KernelInfo::matchKernelConfigs(const std::vector<KernelConfig>& matrixConfigs,
32 std::string* error) const {
33 for (const KernelConfig& matrixConfig : matrixConfigs) {
34 const std::string& key = matrixConfig.first;
35 auto it = this->mConfigs.find(key);
36 if (it == this->mConfigs.end()) {
37 // special case: <value type="tristate">n</value> matches if the config doesn't exist.
38 if (matrixConfig.second == KernelConfigTypedValue::gMissingConfig) {
39 continue;
40 }
41 if (error != nullptr) {
42 *error = "Missing config " + key;
43 }
44 return false;
45 }
46 const std::string& kernelValue = it->second;
47 if (!matrixConfig.second.matchValue(kernelValue)) {
48 if (error != nullptr) {
49 *error = "For config " + key + ", value = " + kernelValue + " but required " +
50 to_string(matrixConfig.second);
51 }
52 return false;
53 }
54 }
55 return true;
56 }
57
matchKernelVersion(const KernelVersion & minLts) const58 bool KernelInfo::matchKernelVersion(const KernelVersion& minLts) const {
59 return minLts.version == mVersion.version && minLts.majorRev == mVersion.majorRev &&
60 minLts.minorRev <= mVersion.minorRev;
61 }
62
matchKernelRequirements(const std::vector<MatrixKernel> & kernels,std::string * error) const63 bool KernelInfo::matchKernelRequirements(const std::vector<MatrixKernel>& kernels,
64 std::string* error) const {
65 bool foundMatchedKernelVersion = false;
66 bool foundMatchedConditions = false;
67 for (const MatrixKernel& matrixKernel : kernels) {
68 if (!matchKernelVersion(matrixKernel.minLts())) {
69 continue;
70 }
71 foundMatchedKernelVersion = true;
72 // ignore this fragment if not all conditions are met.
73 if (!matchKernelConfigs(matrixKernel.conditions(), error)) {
74 continue;
75 }
76 foundMatchedConditions = true;
77 if (!matchKernelConfigs(matrixKernel.configs(), error)) {
78 return false;
79 }
80 }
81 if (!foundMatchedKernelVersion) {
82 if (error != nullptr) {
83 std::stringstream ss;
84 ss << "Framework is incompatible with kernel version " << version()
85 << ", compatible kernel versions are";
86 for (const MatrixKernel& matrixKernel : kernels) ss << " " << matrixKernel.minLts();
87 *error = ss.str();
88 }
89 return false;
90 }
91 if (!foundMatchedConditions) {
92 // This should not happen because first <conditions> for each <kernel> must be
93 // empty. Reject here for inconsistency.
94 if (error != nullptr) {
95 error->insert(0, "Framework match kernel version with unmet conditions:");
96 }
97 return false;
98 }
99 if (error != nullptr) {
100 error->clear();
101 }
102 return true;
103 }
104
operator ==(const KernelInfo & other) const105 bool KernelInfo::operator==(const KernelInfo& other) const {
106 return mVersion == other.mVersion && mConfigs == other.mConfigs;
107 }
108
109 } // namespace vintf
110 } // namespace android
111