xref: /aosp_15_r20/system/libvintf/RuntimeInfo.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 
18*70a7ec85SAndroid Build Coastguard Worker #define LOG_TAG "libvintf"
19*70a7ec85SAndroid Build Coastguard Worker 
20*70a7ec85SAndroid Build Coastguard Worker #include "RuntimeInfo.h"
21*70a7ec85SAndroid Build Coastguard Worker 
22*70a7ec85SAndroid Build Coastguard Worker #include <android-base/logging.h>
23*70a7ec85SAndroid Build Coastguard Worker #include <android-base/strings.h>
24*70a7ec85SAndroid Build Coastguard Worker #include <kver/kernel_release.h>
25*70a7ec85SAndroid Build Coastguard Worker 
26*70a7ec85SAndroid Build Coastguard Worker #include "CompatibilityMatrix.h"
27*70a7ec85SAndroid Build Coastguard Worker #include "parse_string.h"
28*70a7ec85SAndroid Build Coastguard Worker 
29*70a7ec85SAndroid Build Coastguard Worker namespace android {
30*70a7ec85SAndroid Build Coastguard Worker namespace vintf {
31*70a7ec85SAndroid Build Coastguard Worker 
osName() const32*70a7ec85SAndroid Build Coastguard Worker const std::string &RuntimeInfo::osName() const {
33*70a7ec85SAndroid Build Coastguard Worker     return mOsName;
34*70a7ec85SAndroid Build Coastguard Worker }
35*70a7ec85SAndroid Build Coastguard Worker 
nodeName() const36*70a7ec85SAndroid Build Coastguard Worker const std::string &RuntimeInfo::nodeName() const {
37*70a7ec85SAndroid Build Coastguard Worker     return mNodeName;
38*70a7ec85SAndroid Build Coastguard Worker }
39*70a7ec85SAndroid Build Coastguard Worker 
osRelease() const40*70a7ec85SAndroid Build Coastguard Worker const std::string &RuntimeInfo::osRelease() const {
41*70a7ec85SAndroid Build Coastguard Worker     return mOsRelease;
42*70a7ec85SAndroid Build Coastguard Worker }
43*70a7ec85SAndroid Build Coastguard Worker 
osVersion() const44*70a7ec85SAndroid Build Coastguard Worker const std::string &RuntimeInfo::osVersion() const {
45*70a7ec85SAndroid Build Coastguard Worker     return mOsVersion;
46*70a7ec85SAndroid Build Coastguard Worker }
47*70a7ec85SAndroid Build Coastguard Worker 
hardwareId() const48*70a7ec85SAndroid Build Coastguard Worker const std::string &RuntimeInfo::hardwareId() const {
49*70a7ec85SAndroid Build Coastguard Worker     return mHardwareId;
50*70a7ec85SAndroid Build Coastguard Worker }
51*70a7ec85SAndroid Build Coastguard Worker 
kernelVersion() const52*70a7ec85SAndroid Build Coastguard Worker const KernelVersion &RuntimeInfo::kernelVersion() const {
53*70a7ec85SAndroid Build Coastguard Worker     return mKernel.version();
54*70a7ec85SAndroid Build Coastguard Worker }
55*70a7ec85SAndroid Build Coastguard Worker 
kernelConfigs() const56*70a7ec85SAndroid Build Coastguard Worker const std::map<std::string, std::string> &RuntimeInfo::kernelConfigs() const {
57*70a7ec85SAndroid Build Coastguard Worker     return mKernel.configs();
58*70a7ec85SAndroid Build Coastguard Worker }
59*70a7ec85SAndroid Build Coastguard Worker 
kernelSepolicyVersion() const60*70a7ec85SAndroid Build Coastguard Worker size_t RuntimeInfo::kernelSepolicyVersion() const {
61*70a7ec85SAndroid Build Coastguard Worker     return mKernelSepolicyVersion;
62*70a7ec85SAndroid Build Coastguard Worker }
63*70a7ec85SAndroid Build Coastguard Worker 
cpuInfo() const64*70a7ec85SAndroid Build Coastguard Worker const std::string &RuntimeInfo::cpuInfo() const {
65*70a7ec85SAndroid Build Coastguard Worker     return mCpuInfo;
66*70a7ec85SAndroid Build Coastguard Worker }
67*70a7ec85SAndroid Build Coastguard Worker 
bootVbmetaAvbVersion() const68*70a7ec85SAndroid Build Coastguard Worker const Version &RuntimeInfo::bootVbmetaAvbVersion() const {
69*70a7ec85SAndroid Build Coastguard Worker     return mBootVbmetaAvbVersion;
70*70a7ec85SAndroid Build Coastguard Worker }
71*70a7ec85SAndroid Build Coastguard Worker 
bootAvbVersion() const72*70a7ec85SAndroid Build Coastguard Worker const Version &RuntimeInfo::bootAvbVersion() const {
73*70a7ec85SAndroid Build Coastguard Worker     return mBootAvbVersion;
74*70a7ec85SAndroid Build Coastguard Worker }
75*70a7ec85SAndroid Build Coastguard Worker 
isMainlineKernel() const76*70a7ec85SAndroid Build Coastguard Worker bool RuntimeInfo::isMainlineKernel() const {
77*70a7ec85SAndroid Build Coastguard Worker     return mIsMainline;
78*70a7ec85SAndroid Build Coastguard Worker }
79*70a7ec85SAndroid Build Coastguard Worker 
checkCompatibility(const CompatibilityMatrix & mat,std::string * error,CheckFlags::Type flags) const80*70a7ec85SAndroid Build Coastguard Worker bool RuntimeInfo::checkCompatibility(const CompatibilityMatrix& mat, std::string* error,
81*70a7ec85SAndroid Build Coastguard Worker                                      CheckFlags::Type flags) const {
82*70a7ec85SAndroid Build Coastguard Worker     if (mat.mType != SchemaType::FRAMEWORK) {
83*70a7ec85SAndroid Build Coastguard Worker         if (error != nullptr) {
84*70a7ec85SAndroid Build Coastguard Worker             *error = "Should not check runtime info against " + to_string(mat.mType)
85*70a7ec85SAndroid Build Coastguard Worker                     + " compatibility matrix.";
86*70a7ec85SAndroid Build Coastguard Worker         }
87*70a7ec85SAndroid Build Coastguard Worker         return false;
88*70a7ec85SAndroid Build Coastguard Worker     }
89*70a7ec85SAndroid Build Coastguard Worker     if (kernelSepolicyVersion() < mat.framework.mSepolicy.kernelSepolicyVersion()) {
90*70a7ec85SAndroid Build Coastguard Worker         if (error != nullptr) {
91*70a7ec85SAndroid Build Coastguard Worker             *error =
92*70a7ec85SAndroid Build Coastguard Worker                 "kernelSepolicyVersion = " + to_string(kernelSepolicyVersion()) +
93*70a7ec85SAndroid Build Coastguard Worker                 " but required >= " + to_string(mat.framework.mSepolicy.kernelSepolicyVersion());
94*70a7ec85SAndroid Build Coastguard Worker         }
95*70a7ec85SAndroid Build Coastguard Worker         return false;
96*70a7ec85SAndroid Build Coastguard Worker     }
97*70a7ec85SAndroid Build Coastguard Worker 
98*70a7ec85SAndroid Build Coastguard Worker     // mat.mSepolicy.sepolicyVersion() is checked against static
99*70a7ec85SAndroid Build Coastguard Worker     // HalManifest.device.mSepolicyVersion in HalManifest::checkCompatibility.
100*70a7ec85SAndroid Build Coastguard Worker 
101*70a7ec85SAndroid Build Coastguard Worker     if (flags.isKernelEnabled()) {
102*70a7ec85SAndroid Build Coastguard Worker         if (!isMainlineKernel() &&
103*70a7ec85SAndroid Build Coastguard Worker             mKernel.getMatchedKernelRequirements(mat.framework.mKernels, kernelLevel(), error)
104*70a7ec85SAndroid Build Coastguard Worker                 .empty()) {
105*70a7ec85SAndroid Build Coastguard Worker             return false;
106*70a7ec85SAndroid Build Coastguard Worker         }
107*70a7ec85SAndroid Build Coastguard Worker     }
108*70a7ec85SAndroid Build Coastguard Worker 
109*70a7ec85SAndroid Build Coastguard Worker     if (flags.isAvbEnabled()) {
110*70a7ec85SAndroid Build Coastguard Worker         const Version& matAvb = mat.framework.mAvbMetaVersion;
111*70a7ec85SAndroid Build Coastguard Worker         if (mBootAvbVersion.majorVer != matAvb.majorVer ||
112*70a7ec85SAndroid Build Coastguard Worker             mBootAvbVersion.minorVer < matAvb.minorVer) {
113*70a7ec85SAndroid Build Coastguard Worker             if (error != nullptr) {
114*70a7ec85SAndroid Build Coastguard Worker                 std::stringstream ss;
115*70a7ec85SAndroid Build Coastguard Worker                 ss << "AVB version " << mBootAvbVersion << " does not match framework matrix "
116*70a7ec85SAndroid Build Coastguard Worker                    << matAvb;
117*70a7ec85SAndroid Build Coastguard Worker                 *error = ss.str();
118*70a7ec85SAndroid Build Coastguard Worker             }
119*70a7ec85SAndroid Build Coastguard Worker             return false;
120*70a7ec85SAndroid Build Coastguard Worker         }
121*70a7ec85SAndroid Build Coastguard Worker         if (mBootVbmetaAvbVersion.majorVer != matAvb.majorVer ||
122*70a7ec85SAndroid Build Coastguard Worker             mBootVbmetaAvbVersion.minorVer < matAvb.minorVer) {
123*70a7ec85SAndroid Build Coastguard Worker             if (error != nullptr) {
124*70a7ec85SAndroid Build Coastguard Worker                 std::stringstream ss;
125*70a7ec85SAndroid Build Coastguard Worker                 ss << "Vbmeta version " << mBootVbmetaAvbVersion
126*70a7ec85SAndroid Build Coastguard Worker                    << " does not match framework matrix " << matAvb;
127*70a7ec85SAndroid Build Coastguard Worker                 *error = ss.str();
128*70a7ec85SAndroid Build Coastguard Worker             }
129*70a7ec85SAndroid Build Coastguard Worker             return false;
130*70a7ec85SAndroid Build Coastguard Worker         }
131*70a7ec85SAndroid Build Coastguard Worker     }
132*70a7ec85SAndroid Build Coastguard Worker 
133*70a7ec85SAndroid Build Coastguard Worker     return true;
134*70a7ec85SAndroid Build Coastguard Worker }
135*70a7ec85SAndroid Build Coastguard Worker 
setKernelLevel(Level level)136*70a7ec85SAndroid Build Coastguard Worker void RuntimeInfo::setKernelLevel(Level level) {
137*70a7ec85SAndroid Build Coastguard Worker     mKernel.mLevel = level;
138*70a7ec85SAndroid Build Coastguard Worker }
139*70a7ec85SAndroid Build Coastguard Worker 
kernelLevel() const140*70a7ec85SAndroid Build Coastguard Worker Level RuntimeInfo::kernelLevel() const {
141*70a7ec85SAndroid Build Coastguard Worker     return mKernel.mLevel;
142*70a7ec85SAndroid Build Coastguard Worker }
143*70a7ec85SAndroid Build Coastguard Worker 
parseGkiKernelRelease(RuntimeInfo::FetchFlags flags,const std::string & kernelReleaseString,KernelVersion * outVersion,Level * outLevel)144*70a7ec85SAndroid Build Coastguard Worker status_t RuntimeInfo::parseGkiKernelRelease(RuntimeInfo::FetchFlags flags,
145*70a7ec85SAndroid Build Coastguard Worker                                             const std::string& kernelReleaseString,
146*70a7ec85SAndroid Build Coastguard Worker                                             KernelVersion* outVersion, Level* outLevel) {
147*70a7ec85SAndroid Build Coastguard Worker     auto kernelRelease =
148*70a7ec85SAndroid Build Coastguard Worker         android::kver::KernelRelease::Parse(kernelReleaseString, true /* allow suffix */);
149*70a7ec85SAndroid Build Coastguard Worker     if (kernelRelease == std::nullopt) {
150*70a7ec85SAndroid Build Coastguard Worker         return UNKNOWN_ERROR;
151*70a7ec85SAndroid Build Coastguard Worker     }
152*70a7ec85SAndroid Build Coastguard Worker 
153*70a7ec85SAndroid Build Coastguard Worker     if (flags & RuntimeInfo::FetchFlag::CPU_VERSION) {
154*70a7ec85SAndroid Build Coastguard Worker         if (kernelRelease->version() > std::numeric_limits<size_t>::max() ||
155*70a7ec85SAndroid Build Coastguard Worker             kernelRelease->patch_level() > std::numeric_limits<size_t>::max() ||
156*70a7ec85SAndroid Build Coastguard Worker             kernelRelease->sub_level() > std::numeric_limits<size_t>::max()) {
157*70a7ec85SAndroid Build Coastguard Worker             LOG(ERROR) << "Overflow : " << kernelRelease->string();
158*70a7ec85SAndroid Build Coastguard Worker             return UNKNOWN_ERROR;
159*70a7ec85SAndroid Build Coastguard Worker         }
160*70a7ec85SAndroid Build Coastguard Worker         *outVersion = {static_cast<size_t>(kernelRelease->version()),
161*70a7ec85SAndroid Build Coastguard Worker                        static_cast<size_t>(kernelRelease->patch_level()),
162*70a7ec85SAndroid Build Coastguard Worker                        static_cast<size_t>(kernelRelease->sub_level())};
163*70a7ec85SAndroid Build Coastguard Worker     }
164*70a7ec85SAndroid Build Coastguard Worker 
165*70a7ec85SAndroid Build Coastguard Worker     if (flags & RuntimeInfo::FetchFlag::KERNEL_FCM) {
166*70a7ec85SAndroid Build Coastguard Worker         Level kernelLevel = gkiAndroidReleaseToLevel(kernelRelease->android_release());
167*70a7ec85SAndroid Build Coastguard Worker         if (kernelLevel == Level::UNSPECIFIED) {
168*70a7ec85SAndroid Build Coastguard Worker             LOG(ERROR) << "Cannot infer level corresponding to Android "
169*70a7ec85SAndroid Build Coastguard Worker                        << kernelRelease->android_release()
170*70a7ec85SAndroid Build Coastguard Worker                        << "; update libvintf to recognize this value.";
171*70a7ec85SAndroid Build Coastguard Worker             return UNKNOWN_ERROR;
172*70a7ec85SAndroid Build Coastguard Worker         }
173*70a7ec85SAndroid Build Coastguard Worker         // VintfObject may previously set mRuntimeInfo->mKernel.mLevel to the kernel level
174*70a7ec85SAndroid Build Coastguard Worker         // from device manifest. Check consistency.
175*70a7ec85SAndroid Build Coastguard Worker         if (*outLevel != Level::UNSPECIFIED && *outLevel != kernelLevel) {
176*70a7ec85SAndroid Build Coastguard Worker             LOG(ERROR) << "Kernel level in device manifest (" << *outLevel
177*70a7ec85SAndroid Build Coastguard Worker                        << ") does not match kernel level in kernel release (" << kernelLevel
178*70a7ec85SAndroid Build Coastguard Worker                        << " for Android " << kernelRelease->android_release() << ")";
179*70a7ec85SAndroid Build Coastguard Worker             return UNKNOWN_ERROR;
180*70a7ec85SAndroid Build Coastguard Worker         }
181*70a7ec85SAndroid Build Coastguard Worker         *outLevel = kernelLevel;
182*70a7ec85SAndroid Build Coastguard Worker     }
183*70a7ec85SAndroid Build Coastguard Worker     return OK;
184*70a7ec85SAndroid Build Coastguard Worker }
185*70a7ec85SAndroid Build Coastguard Worker 
gkiAndroidReleaseToLevel(uint64_t androidRelease)186*70a7ec85SAndroid Build Coastguard Worker Level RuntimeInfo::gkiAndroidReleaseToLevel(uint64_t androidRelease) {
187*70a7ec85SAndroid Build Coastguard Worker     constexpr size_t ANDROID_S = 12;
188*70a7ec85SAndroid Build Coastguard Worker     constexpr size_t ANDROID_V = 15;
189*70a7ec85SAndroid Build Coastguard Worker 
190*70a7ec85SAndroid Build Coastguard Worker     // Values prior to Android 12 is ignored because GKI kernel release format starts
191*70a7ec85SAndroid Build Coastguard Worker     // at Android 12.
192*70a7ec85SAndroid Build Coastguard Worker     if (androidRelease < ANDROID_S) return Level::UNSPECIFIED;
193*70a7ec85SAndroid Build Coastguard Worker 
194*70a7ec85SAndroid Build Coastguard Worker     Level ret = Level::UNSPECIFIED;
195*70a7ec85SAndroid Build Coastguard Worker     if (androidRelease < ANDROID_V) {
196*70a7ec85SAndroid Build Coastguard Worker         ret = static_cast<Level>(androidRelease - ANDROID_S + static_cast<size_t>(Level::S));
197*70a7ec85SAndroid Build Coastguard Worker     } else {
198*70a7ec85SAndroid Build Coastguard Worker         switch (androidRelease) {
199*70a7ec85SAndroid Build Coastguard Worker             case 15: {
200*70a7ec85SAndroid Build Coastguard Worker                 ret = Level::V;
201*70a7ec85SAndroid Build Coastguard Worker             } break;
202*70a7ec85SAndroid Build Coastguard Worker             case 16: {
203*70a7ec85SAndroid Build Coastguard Worker                 ret = Level::W;
204*70a7ec85SAndroid Build Coastguard Worker             } break;
205*70a7ec85SAndroid Build Coastguard Worker             // Add more levels above this line.
206*70a7ec85SAndroid Build Coastguard Worker             default: {
207*70a7ec85SAndroid Build Coastguard Worker                 LOG(FATAL) << "Convert Android " << androidRelease << " to level '" << ret
208*70a7ec85SAndroid Build Coastguard Worker                            << "' goes out of bounds. Fix by editing "
209*70a7ec85SAndroid Build Coastguard Worker                            << "RuntimeInfo::gkiAndroidReleaseToLevel";
210*70a7ec85SAndroid Build Coastguard Worker             } break;
211*70a7ec85SAndroid Build Coastguard Worker         }
212*70a7ec85SAndroid Build Coastguard Worker     }
213*70a7ec85SAndroid Build Coastguard Worker 
214*70a7ec85SAndroid Build Coastguard Worker     CHECK(IsValid(ret) && ret != Level::UNSPECIFIED)
215*70a7ec85SAndroid Build Coastguard Worker         << "Convert Android " << androidRelease << " to level '" << ret
216*70a7ec85SAndroid Build Coastguard Worker         << "' goes out of bounds. Fix by adding a new Level enum.";
217*70a7ec85SAndroid Build Coastguard Worker     return ret;
218*70a7ec85SAndroid Build Coastguard Worker }
219*70a7ec85SAndroid Build Coastguard Worker 
kernelReleaseIsMainline(std::string_view kernelRelease)220*70a7ec85SAndroid Build Coastguard Worker bool RuntimeInfo::kernelReleaseIsMainline(std::string_view kernelRelease) {
221*70a7ec85SAndroid Build Coastguard Worker     static constexpr char kMainline[] = "-mainline-";
222*70a7ec85SAndroid Build Coastguard Worker     static constexpr char kMainlineSuffix[] = "-mainline";
223*70a7ec85SAndroid Build Coastguard Worker 
224*70a7ec85SAndroid Build Coastguard Worker     return kernelRelease.find(kMainline) != std::string::npos ||
225*70a7ec85SAndroid Build Coastguard Worker            android::base::EndsWith(kernelRelease, kMainlineSuffix);
226*70a7ec85SAndroid Build Coastguard Worker }
227*70a7ec85SAndroid Build Coastguard Worker 
228*70a7ec85SAndroid Build Coastguard Worker } // namespace vintf
229*70a7ec85SAndroid Build Coastguard Worker } // namespace android
230