1/*
2 * Copyright (C) 2017 The Android Open Source Project
3 *
4 * Licensed under the Apache License, Version 2.0 (the "License");
5 * you may not use this file except in compliance with the License.
6 * You may obtain a copy of the License at
7 *
8 *      http://www.apache.org/licenses/LICENSE-2.0
9 *
10 * Unless required by applicable law or agreed to in writing, software
11 * distributed under the License is distributed on an "AS IS" BASIS,
12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 * See the License for the specific language governing permissions and
14 * limitations under the License.
15 */
16
17
18#define LOG_TAG "libvintf"
19
20#include "RuntimeInfo.h"
21
22#include "CompatibilityMatrix.h"
23#include "parse_string.h"
24
25namespace android {
26namespace vintf {
27
28const std::string &RuntimeInfo::osName() const {
29    return mOsName;
30}
31
32const std::string &RuntimeInfo::nodeName() const {
33    return mNodeName;
34}
35
36const std::string &RuntimeInfo::osRelease() const {
37    return mOsRelease;
38}
39
40const std::string &RuntimeInfo::osVersion() const {
41    return mOsVersion;
42}
43
44const std::string &RuntimeInfo::hardwareId() const {
45    return mHardwareId;
46}
47
48const KernelVersion &RuntimeInfo::kernelVersion() const {
49    return mKernelVersion;
50}
51
52const std::map<std::string, std::string> &RuntimeInfo::kernelConfigs() const {
53    return mKernelConfigs;
54}
55
56size_t RuntimeInfo::kernelSepolicyVersion() const {
57    return mKernelSepolicyVersion;
58}
59
60const std::string &RuntimeInfo::cpuInfo() const {
61    return mCpuInfo;
62}
63
64const Version &RuntimeInfo::bootVbmetaAvbVersion() const {
65    return mBootVbmetaAvbVersion;
66}
67
68const Version &RuntimeInfo::bootAvbVersion() const {
69    return mBootAvbVersion;
70}
71
72bool RuntimeInfo::matchKernelConfigs(const std::vector<KernelConfig>& matrixConfigs,
73                                     std::string* error) const {
74    for (const KernelConfig& matrixConfig : matrixConfigs) {
75        const std::string& key = matrixConfig.first;
76        auto it = this->mKernelConfigs.find(key);
77        if (it == this->mKernelConfigs.end()) {
78            // special case: <value type="tristate">n</value> matches if the config doesn't exist.
79            if (matrixConfig.second == KernelConfigTypedValue::gMissingConfig) {
80                continue;
81            }
82            if (error != nullptr) {
83                *error = "Missing config " + key;
84            }
85            return false;
86        }
87        const std::string& kernelValue = it->second;
88        if (!matrixConfig.second.matchValue(kernelValue)) {
89            if (error != nullptr) {
90                *error = "For config " + key + ", value = " + kernelValue + " but required " +
91                         to_string(matrixConfig.second);
92            }
93            return false;
94        }
95    }
96    return true;
97}
98
99bool RuntimeInfo::matchKernelVersion(const KernelVersion& minLts) const {
100    return minLts.version == mKernelVersion.version && minLts.majorRev == mKernelVersion.majorRev &&
101           minLts.minorRev <= mKernelVersion.minorRev;
102}
103
104bool RuntimeInfo::checkCompatibility(const CompatibilityMatrix& mat, std::string* error,
105                                     DisabledChecks disabledChecks) const {
106    if (mat.mType != SchemaType::FRAMEWORK) {
107        if (error != nullptr) {
108            *error = "Should not check runtime info against " + to_string(mat.mType)
109                    + " compatibility matrix.";
110        }
111        return false;
112    }
113    if (kernelSepolicyVersion() < mat.framework.mSepolicy.kernelSepolicyVersion()) {
114        if (error != nullptr) {
115            *error =
116                "kernelSepolicyVersion = " + to_string(kernelSepolicyVersion()) +
117                " but required >= " + to_string(mat.framework.mSepolicy.kernelSepolicyVersion());
118        }
119        return false;
120    }
121
122    // mat.mSepolicy.sepolicyVersion() is checked against static
123    // HalManifest.device.mSepolicyVersion in HalManifest::checkCompatibility.
124
125    bool foundMatchedKernelVersion = false;
126    bool foundMatchedConditions = false;
127    for (const MatrixKernel& matrixKernel : mat.framework.mKernels) {
128        if (!matchKernelVersion(matrixKernel.minLts())) {
129            continue;
130        }
131        foundMatchedKernelVersion = true;
132        // ignore this fragment if not all conditions are met.
133        if (!matchKernelConfigs(matrixKernel.conditions(), error)) {
134            continue;
135        }
136        foundMatchedConditions = true;
137        if (!matchKernelConfigs(matrixKernel.configs(), error)) {
138            return false;
139        }
140    }
141    if (!foundMatchedKernelVersion) {
142        if (error != nullptr) {
143            std::stringstream ss;
144            ss << "Framework is incompatible with kernel version " << mKernelVersion
145               << ", compatible kernel versions are";
146            for (const MatrixKernel& matrixKernel : mat.framework.mKernels)
147                ss << " " << matrixKernel.minLts();
148            *error = ss.str();
149        }
150        return false;
151    }
152    if (!foundMatchedConditions) {
153        // This should not happen because first <conditions> for each <kernel> must be
154        // empty. Reject here for inconsistency.
155        if (error != nullptr) {
156            error->insert(0, "Framework match kernel version with unmet conditions:");
157        }
158        return false;
159    }
160    if (error != nullptr) {
161        error->clear();
162    }
163
164    if ((disabledChecks & DISABLE_AVB_CHECK) == 0) {
165        const Version& matAvb = mat.framework.mAvbMetaVersion;
166        if (mBootAvbVersion.majorVer != matAvb.majorVer ||
167            mBootAvbVersion.minorVer < matAvb.minorVer) {
168            if (error != nullptr) {
169                std::stringstream ss;
170                ss << "AVB version " << mBootAvbVersion << " does not match framework matrix "
171                   << matAvb;
172                *error = ss.str();
173            }
174            return false;
175        }
176        if (mBootVbmetaAvbVersion.majorVer != matAvb.majorVer ||
177            mBootVbmetaAvbVersion.minorVer < matAvb.minorVer) {
178            if (error != nullptr) {
179                std::stringstream ss;
180                ss << "Vbmeta version " << mBootVbmetaAvbVersion
181                   << " does not match framework matrix " << matAvb;
182                *error = ss.str();
183            }
184            return false;
185        }
186    }
187
188    return true;
189}
190
191} // namespace vintf
192} // namespace android
193