1 /*
2 * Copyright (C) 2022 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 package com.android.cts.kernelinfo
18
19 import android.app.UiAutomation
20 import android.os.ParcelFileDescriptor
21 import android.os.VintfRuntimeInfo
22 import android.text.TextUtils
23 import android.util.Pair
24 import androidx.test.platform.app.InstrumentationRegistry
25 import java.io.BufferedReader
26 import java.io.InputStream
27 import java.io.InputStreamReader
28 import java.util.regex.Pattern
29 import java.util.stream.Collectors
30 import org.junit.Assert.fail
31
isCommentnull32 private fun isComment(s: String): Boolean {
33 return s.trim().startsWith("#")
34 }
35
compareMajorMinorVersionnull36 private fun compareMajorMinorVersion(s1: String, s2: String): Int {
37 val v1: Pair<Int, Int> = getVersionFromString(s1)
38 val v2: Pair<Int, Int> = getVersionFromString(s2)
39 return if (v1.first == v2.first) {
40 Integer.compare(v1.second, v2.second)
41 } else {
42 Integer.compare(v1.first, v2.first)
43 }
44 }
45
getVersionFromStringnull46 private fun getVersionFromString(version: String): Pair<Int, Int> {
47 // Only gets major and minor number of the version string.
48 val versionPattern = Pattern.compile("^(\\d+)(\\.(\\d+))?.*")
49 val m = versionPattern.matcher(version)
50 if (!m.matches()) {
51 fail("Cannot parse kernel version: $version")
52 }
53 val major = m.group(1).toInt()
54 val minor = if (TextUtils.isEmpty(m.group(3))) 0 else m.group(3).toInt()
55 return Pair(major, minor)
56 }
57
58 /**
59 * A class that reads various kernel properties
60 */
61 abstract class KernelInfo {
62 companion object {
63 /*
64 * The kernel configs on this device. The value is cached.
65 */
66 private val sConfigs: Set<String>
67
68 /**
69 * Return true if the specified config is enabled, false otherwise.
70 */
71 @JvmStatic
hasConfignull72 fun hasConfig(config: String): Boolean {
73 return sConfigs.contains("$config=y") || sConfigs.contains("$config=m")
74 }
75
76 /**
77 * Return true if the device's kernel version is newer than the provided version,
78 * false otherwise
79 */
80 @JvmStatic
isKernelVersionGreaterThannull81 fun isKernelVersionGreaterThan(version: String): Boolean {
82 val actualVersion = VintfRuntimeInfo.getKernelVersion()
83 return compareMajorMinorVersion(actualVersion, version) > 0
84 }
85
86 init {
87 val automation: UiAutomation = InstrumentationRegistry.getInstrumentation().uiAutomation
88 // Access /proc/config.gz from the shell domain, because it cannot be accessed from the
89 // app domain
90 val stdout: ParcelFileDescriptor =
91 automation.executeShellCommand("zcat /proc/config.gz")
92 val inputStream: InputStream = ParcelFileDescriptor.AutoCloseInputStream(stdout)
<lambda>null93 inputStream.use {
94 val reader = BufferedReader(InputStreamReader(inputStream))
95 // Remove any lines that are comments
96 sConfigs = reader.lines().filter {!isComment(it)}.collect(Collectors.toSet())
97 }
98 }
99 }
100 }
101