1 /*
2 * Copyright (C) 2023 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 #include <algorithm>
18 #include <memory>
19 #include <optional>
20 #include <ostream>
21 #include <sstream>
22 #include <string>
23
24 #include <android-base/file.h>
25 #include <android-base/parseint.h>
26 #include <android-base/properties.h>
27 #include <android-base/result-gmock.h>
28 #include <android-base/strings.h>
29 #include <android/api-level.h>
30 #include <gmock/gmock.h>
31 #include <google/protobuf/repeated_field.h>
32 #include <google/protobuf/text_format.h>
33 #include <gtest/gtest.h>
34 #include <kver/kernel_release.h>
35 #include <libvts_vintf_test_common/common.h>
36 #include <vintf/Version.h>
37 #include <vintf/VintfObject.h>
38 #include <vintf/parse_string.h>
39
40 #include "gsi_validation_utils.h"
41 #include "kernel_version_matrix.pb.h"
42
43 namespace {
44
45 using android::base::testing::Ok;
46 using KernelVersionMatrix = std::map<uint64_t, AndroidReleaseRequirement>;
47
operator <<(std::ostream & os,const Kmi & kmi)48 std::ostream& operator<<(std::ostream& os, const Kmi& kmi) {
49 os << "android";
50 if (kmi.android_release() != 0) {
51 os << kmi.android_release();
52 }
53 return os << "-" << kmi.kernel_version().major_version() << "."
54 << kmi.kernel_version().minor_version();
55 }
56
57 // Represents the information about the running kernel.
58 struct ActualKmi {
59 public:
ActualKmi__anon0455a8e80111::ActualKmi60 ActualKmi(const android::vintf::KernelVersion& kernel_version,
61 const std::optional<android::kver::KernelRelease>& kernel_release)
62 : kernel_version_(kernel_version), kernel_release_(kernel_release) {}
63
kernel_version__anon0455a8e80111::ActualKmi64 [[nodiscard]] android::vintf::Version kernel_version() const {
65 return kernel_version_.dropMinor();
66 }
67
android_release__anon0455a8e80111::ActualKmi68 [[nodiscard]] std::optional<uint64_t> android_release() const {
69 if (kernel_release_.has_value()) {
70 return kernel_release_->android_release();
71 }
72 return std::nullopt;
73 }
74
string__anon0455a8e80111::ActualKmi75 [[nodiscard]] std::string string() const {
76 std::string ret = android::vintf::to_string(kernel_version_);
77 if (kernel_release_.has_value()) {
78 ret += " (" + kernel_release_->string() + ")";
79 }
80 return ret;
81 }
82
operator <<(std::ostream & os,const ActualKmi & kmi)83 friend std::ostream& operator<<(std::ostream& os, const ActualKmi& kmi) {
84 os << kmi.kernel_version_;
85 if (kmi.kernel_release_.has_value()) {
86 os << " (" + kmi.kernel_release_->string() << ")";
87 }
88 return os;
89 }
90
91 private:
92 android::vintf::KernelVersion kernel_version_;
93 std::optional<android::kver::KernelRelease> kernel_release_;
94 };
95
96 // Read the raw compatibility matrix from test data.
ReadRawKernelVersionMatrix()97 std::optional<RawKernelVersionMatrix> ReadRawKernelVersionMatrix() {
98 auto exec_dir = android::base::GetExecutableDirectory();
99 auto matrix_path = exec_dir + "/kernel_version_matrix.textproto";
100 std::string matrix_content;
101 if (!android::base::ReadFileToString(matrix_path, &matrix_content)) {
102 ADD_FAILURE() << "Can't read " << matrix_path;
103 return std::nullopt;
104 }
105
106 RawKernelVersionMatrix ret;
107 if (!google::protobuf::TextFormat::ParseFromString(matrix_content, &ret)) {
108 ADD_FAILURE() << matrix_path << " is not valid";
109 return std::nullopt;
110 }
111 return ret;
112 }
113
114 // Parse a raw KMI string (e.g. "android14-5.15") to structured Kmi object.
FromRaw(const std::string & s,Kmi * mutable_out)115 bool FromRaw(const std::string& s, Kmi* mutable_out) {
116 auto tokens = android::base::Split(s, "-");
117 if (tokens.size() != 2) {
118 ADD_FAILURE() << "Unrecognized requirement: " << s;
119 return false;
120 }
121
122 std::string_view android_release_sv = tokens[0];
123 if (!android::base::ConsumePrefix(&android_release_sv, "android")) {
124 ADD_FAILURE() << "Unrecognized requirement: " << s;
125 return false;
126 }
127
128 uint64_t android_release;
129 if (android_release_sv.empty()) {
130 mutable_out->clear_android_release();
131 } else {
132 if (!android::base::ParseUint(std::string(android_release_sv),
133 &android_release)) {
134 ADD_FAILURE() << "Unrecognized requirement: " << s;
135 return false;
136 }
137 mutable_out->set_android_release(android_release);
138 }
139
140 android::vintf::Version vintf_kernel_version;
141 if (!android::vintf::parse(tokens[1], &vintf_kernel_version)) {
142 ADD_FAILURE() << "Unrecognized requirement: " << s;
143 return false;
144 }
145 mutable_out->mutable_kernel_version()->set_major_version(
146 vintf_kernel_version.majorVer);
147 mutable_out->mutable_kernel_version()->set_minor_version(
148 vintf_kernel_version.minorVer);
149
150 return true;
151 }
152
153 // Parse an array of raw KMI strings to an array of structured Kmi object.
FromRaw(const google::protobuf::RepeatedPtrField<std::string> & raw_in,google::protobuf::RepeatedPtrField<Kmi> * mutable_out)154 bool FromRaw(const google::protobuf::RepeatedPtrField<std::string>& raw_in,
155 google::protobuf::RepeatedPtrField<Kmi>* mutable_out) {
156 mutable_out->Reserve(raw_in.size());
157 for (const auto& raw_s : raw_in) {
158 if (!FromRaw(raw_s, mutable_out->Add())) {
159 return false;
160 }
161 }
162 return true;
163 }
164
165 // Turn the raw compatibility matrix into structured data.
FromRaw(const RawKernelVersionMatrix & raw_kernel_version_matrix)166 std::optional<KernelVersionMatrix> FromRaw(
167 const RawKernelVersionMatrix& raw_kernel_version_matrix) {
168 KernelVersionMatrix ret;
169 for (const auto& [api_level, raw_android_release_requirements] :
170 raw_kernel_version_matrix.release_requirements()) {
171 AndroidReleaseRequirement ret_value;
172 if (!FromRaw(raw_android_release_requirements.upgrade(),
173 ret_value.mutable_upgrade())) {
174 return std::nullopt;
175 }
176 if (!FromRaw(raw_android_release_requirements.launch(),
177 ret_value.mutable_launch())) {
178 return std::nullopt;
179 }
180 if (!FromRaw(raw_android_release_requirements.launch_grf(),
181 ret_value.mutable_launch_grf())) {
182 return std::nullopt;
183 }
184 ret.emplace(api_level, std::move(ret_value));
185 }
186 return ret;
187 }
188
189 // Return requirements on kernel version and KMI for the given platform SDK
190 // level. Return nullptr on failure.
GetKernelVersionRequirements(const KernelVersionMatrix & kernel_version_matrix,uint32_t android_platform_release,bool is_launch,bool is_grf)191 const google::protobuf::RepeatedPtrField<Kmi>* GetKernelVersionRequirements(
192 const KernelVersionMatrix& kernel_version_matrix,
193 uint32_t android_platform_release, bool is_launch, bool is_grf) {
194 auto release_requirements_it =
195 kernel_version_matrix.find(android_platform_release);
196 if (release_requirements_it == kernel_version_matrix.end()) {
197 ADD_FAILURE() << "Unable to find requirement for SDK level "
198 << android_platform_release << ". Is the test updated?";
199 return nullptr;
200 }
201
202 if (is_launch) {
203 if (is_grf) {
204 return &release_requirements_it->second.launch_grf();
205 }
206 return &release_requirements_it->second.launch();
207 }
208 return &release_requirements_it->second.upgrade();
209 }
210
211 // Read the information about the running kernel that this test needs.
GetActualKmi()212 std::optional<ActualKmi> GetActualKmi() {
213 auto vintf_object = android::vintf::VintfObject::GetInstance();
214 if (vintf_object == nullptr) {
215 ADD_FAILURE() << "Cannot get VintfObject instance";
216 return std::nullopt;
217 }
218 auto runtime_info = vintf_object->getRuntimeInfo(
219 android::vintf::RuntimeInfo::FetchFlag::CPU_VERSION);
220 if (runtime_info == nullptr) {
221 ADD_FAILURE() << "Cannot get kernel release";
222 return std::nullopt;
223 }
224
225 auto kernel_release = android::kver::KernelRelease::Parse(
226 runtime_info->osRelease(), true /* allow suffix */);
227 auto kernel_version = runtime_info->kernelVersion();
228
229 return std::make_optional<ActualKmi>(kernel_version, kernel_release);
230 }
231
232 // Check kernel version and KMI against a list of requirements.
KernelVersionIsSupported(const ActualKmi & actual,const google::protobuf::RepeatedPtrField<Kmi> & requirements,std::string * error)233 bool KernelVersionIsSupported(
234 const ActualKmi& actual,
235 const google::protobuf::RepeatedPtrField<Kmi>& requirements,
236 std::string* error) {
237 for (const auto& req : requirements) {
238 if (req.kernel_version().major_version() !=
239 actual.kernel_version().majorVer ||
240 req.kernel_version().minor_version() !=
241 actual.kernel_version().minorVer) {
242 GTEST_LOG_(INFO) << "Failed to match " << actual << " against required "
243 << req << ": kernel version does not match.";
244 continue; // check next item
245 }
246
247 if (req.android_release() != actual.android_release().value_or(0)) {
248 GTEST_LOG_(INFO) << "Failed to match " << actual << " against required "
249 << req
250 << ": The Android release part of KMI does not match.";
251 continue; // check next item
252 }
253
254 GTEST_LOG_(INFO) << "Matched " << actual << " against requirement " << req;
255 return true;
256 }
257
258 std::stringstream error_stream;
259 error_stream << "Kernel " << actual << " is not valid. It must be one of [\n";
260 for (const auto& req : requirements) {
261 error_stream << " " << req << ",\n";
262 }
263 error_stream << "].";
264 *error = error_stream.str();
265 return false;
266 }
267
268 // If ro.build.version.codename == REL, expect the given condition is true.
269 // Otherwise, only log a warning message, but don't fail the test.
270 struct ExpectTrueOnRelease : public std::stringstream {
ExpectTrueOnRelease__anon0455a8e80111::ExpectTrueOnRelease271 explicit ExpectTrueOnRelease(bool cond) : cond_(cond) {}
~ExpectTrueOnRelease__anon0455a8e80111::ExpectTrueOnRelease272 ~ExpectTrueOnRelease() override {
273 if (cond_) {
274 return;
275 }
276 if (!IsReleasedAndroidVersion()) {
277 GTEST_LOG_(ERROR) << str() << " This will be an error upon release.";
278 } else {
279 ADD_FAILURE() << str();
280 }
281 }
282
283 private:
284 bool cond_;
285 };
286
IsGrf()287 bool IsGrf() {
288 return !android::base::GetProperty("ro.board.first_api_level", "").empty();
289 }
290
291 // Returns true if the device has the specified feature.
DeviceSupportsFeature(const char * feature)292 bool DeviceSupportsFeature(const char* feature) {
293 bool device_supports_feature = false;
294 FILE* p = popen("pm list features", "re");
295 if (p) {
296 char* line = NULL;
297 size_t len = 0;
298 while (getline(&line, &len, p) > 0) {
299 if (strstr(line, feature)) {
300 device_supports_feature = true;
301 break;
302 }
303 }
304 pclose(p);
305 }
306 return device_supports_feature;
307 }
308
TEST(KernelVersionTest,AgainstPlatformRelease)309 TEST(KernelVersionTest, AgainstPlatformRelease) {
310 auto raw_kernel_version_matrix = ReadRawKernelVersionMatrix();
311 ASSERT_TRUE(raw_kernel_version_matrix.has_value());
312 ASSERT_GT(raw_kernel_version_matrix->release_requirements_size(), 0);
313
314 auto kernel_version_matrix = FromRaw(*raw_kernel_version_matrix);
315 ASSERT_TRUE(kernel_version_matrix.has_value());
316 ASSERT_FALSE(kernel_version_matrix->empty());
317
318 auto android_platform_release = GetSdkLevel();
319
320 auto min_enforcing_android_release = kernel_version_matrix->begin()->first;
321 if (android_platform_release < min_enforcing_android_release) {
322 GTEST_SKIP() << "Kernel version is not enforced for platform SDK level "
323 << android_platform_release << " ( < "
324 << min_enforcing_android_release << " )";
325 }
326
327 auto product_first_api_level = GetProductFirstApiLevel();
328 ExpectTrueOnRelease(product_first_api_level <= android_platform_release)
329 << "Product first API level " << product_first_api_level
330 << " should not exceed the platform release " << android_platform_release
331 << ".";
332
333 const static bool is_tv_device =
334 DeviceSupportsFeature("android.software.leanback");
335 if (product_first_api_level <= 33 && is_tv_device) {
336 GTEST_SKIP()
337 << "Exempt from GKI test on TV devices launched before Android U";
338 }
339
340 bool is_launch = product_first_api_level >= android_platform_release;
341
342 auto requirements = GetKernelVersionRequirements(
343 *kernel_version_matrix, android_platform_release, is_launch, IsGrf());
344 ASSERT_NE(requirements, nullptr);
345
346 auto actual = GetActualKmi();
347 ASSERT_TRUE(actual.has_value());
348
349 std::string error;
350 ExpectTrueOnRelease(KernelVersionIsSupported(*actual, *requirements, &error))
351 << error;
352 }
353
TEST(KernelVersionTest,GrfDevicesMustUseLatestKernel)354 TEST(KernelVersionTest, GrfDevicesMustUseLatestKernel) {
355 if (!IsGrf()) {
356 GTEST_SKIP() << "Non-GRF device kernel requirements are checked in "
357 "SystemVendorTest.KernelCompatibility";
358 }
359
360 auto vendor_api_level = GetVendorApiLevel();
361 ASSERT_TRUE(vendor_api_level != 0)
362 << "Unable to determine board API level on GRF devices";
363
364 if (vendor_api_level <= __ANDROID_API_R__) {
365 GTEST_SKIP() << "[VSR-3.4.1-001] does not enforce latest kernel x.y for "
366 << "vendor_api_level == " << vendor_api_level << " <= R";
367 }
368
369 auto corresponding_vintf_level =
370 android::vintf::testing::GetFcmVersionFromApiLevel(vendor_api_level);
371 ASSERT_THAT(corresponding_vintf_level, Ok());
372
373 auto latest_min_lts =
374 android::vintf::VintfObject::GetInstance()->getLatestMinLtsAtFcmVersion(
375 *corresponding_vintf_level);
376 ASSERT_THAT(latest_min_lts, Ok());
377 auto runtime_info =
378 android::vintf::VintfObject::GetInstance()->getRuntimeInfo(
379 android::vintf::RuntimeInfo::FetchFlag::CPU_VERSION);
380 ASSERT_NE(runtime_info, nullptr);
381 auto kernel_version = runtime_info->kernelVersion();
382
383 ASSERT_GE(kernel_version, *latest_min_lts)
384 << "[VSR-3.4.1-001] CHIPSETs that are on GRF and are frozen on API level "
385 << vendor_api_level << " (corresponding to VINTF level "
386 << *corresponding_vintf_level << ") must use kernel version ("
387 << *latest_min_lts << ")+, but kernel version is " << kernel_version;
388 }
389
390 } // namespace
391