1 /* 2 * Copyright (C) 2020 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.tests.fastboot_getvar; 18 19 import static org.junit.Assert.assertEquals; 20 import static org.junit.Assert.assertTrue; 21 import static org.junit.Assert.fail; 22 23 import com.android.tradefed.device.ITestDevice; 24 import com.android.tradefed.device.TestDeviceState; 25 import com.android.tradefed.invoker.TestInformation; 26 import com.android.tradefed.log.LogUtil.CLog; 27 import com.android.tradefed.testtype.DeviceJUnit4ClassRunner; 28 import com.android.tradefed.testtype.junit4.AfterClassWithInfo; 29 import com.android.tradefed.testtype.junit4.BaseHostJUnit4Test; 30 import com.android.tradefed.util.AbiFormatter; 31 import java.text.ParseException; 32 import java.text.SimpleDateFormat; 33 import java.util.ArrayList; 34 import java.util.Arrays; 35 import java.util.HashSet; 36 import java.util.regex.Matcher; 37 import java.util.regex.Pattern; 38 import org.junit.Assert; 39 import org.junit.Assume; 40 import org.junit.Before; 41 import org.junit.Test; 42 import org.junit.runner.RunWith; 43 44 /* VTS test to verify userspace fastboot getvar information. */ 45 @RunWith(DeviceJUnit4ClassRunner.class) 46 public class FastbootGetvarUserspaceTest extends BaseHostJUnit4Test { 47 private static final int PLATFORM_API_LEVEL_R = 30; 48 private static final int ANDROID_RELEASE_VERSION_R = 11; 49 50 private ITestDevice mDevice; 51 52 @Before setUp()53 public void setUp() throws Exception { 54 mDevice = getDevice(); 55 56 ArrayList<String> supportedAbis = new ArrayList<>(Arrays.asList(AbiFormatter.getSupportedAbis(mDevice, ""))); 57 if (supportedAbis.contains("arm64-v8a")) { 58 String output = mDevice.executeShellCommand("uname -r"); 59 Pattern p = Pattern.compile("^(\\d+)\\.(\\d+)"); 60 Matcher m1 = p.matcher(output); 61 Assert.assertTrue(m1.find()); 62 Assume.assumeTrue("Skipping test for fastbootd on GKI", 63 Integer.parseInt(m1.group(1)) < 5 || 64 (Integer.parseInt(m1.group(1)) == 5 && 65 Integer.parseInt(m1.group(2)) < 4)); 66 } 67 68 // Make sure the device is in fastbootd mode. 69 if (!TestDeviceState.FASTBOOT.equals(mDevice.getDeviceState())) { 70 mDevice.rebootIntoFastbootd(); 71 } 72 } 73 74 @AfterClassWithInfo tearDownClass(TestInformation testInfo)75 public static void tearDownClass(TestInformation testInfo) throws Exception { 76 testInfo.getDevice().reboot(); 77 } 78 79 /* Devices launching in R and after must export cpu-abi. */ 80 @Test testCpuAbiInfo()81 public void testCpuAbiInfo() throws Exception { 82 final HashSet<String> allCpuAbis = new HashSet<String>( 83 Arrays.asList("armeabi-v7a", "arm64-v8a", "mips", "mips64", "x86", "x86_64")); 84 String cpuAbi = mDevice.getFastbootVariable("cpu-abi"); 85 CLog.d("cpuAbi: '%s'", cpuAbi); 86 assertTrue(allCpuAbis.contains(cpuAbi)); 87 } 88 89 /* Devices launching in R and after must export version-os. */ 90 @Test testOsVersion()91 public void testOsVersion() throws Exception { 92 String osVersion = mDevice.getFastbootVariable("version-os"); 93 CLog.d("os version: '%s'", osVersion); 94 // The value of osVersion might be a letter on pre-release builds, e.g., R, 95 // or is a number representing the Android release version, e.g., 11. 96 try { 97 int intOsVersion = Integer.parseInt(osVersion); 98 assertTrue(intOsVersion >= ANDROID_RELEASE_VERSION_R); 99 } catch (NumberFormatException nfe) { 100 assertTrue(osVersion.matches("[A-Z]+")); 101 } 102 } 103 104 /* Devices launching in R and after must export version-vndk. */ 105 @Test testVndkVersion()106 public void testVndkVersion() throws Exception { 107 String vndkVersion = mDevice.getFastbootVariable("version-vndk"); 108 CLog.d("vndk version: '%s'", vndkVersion); 109 // The value of vndkVersion might be a letter on pre-release builds, e.g., R, 110 // or is a number representing the API level on final release builds, e.g., 30. 111 try { 112 int intVndkVersion = Integer.parseInt(vndkVersion); 113 assertTrue(intVndkVersion >= PLATFORM_API_LEVEL_R); 114 } catch (NumberFormatException nfe) { 115 assertTrue(vndkVersion.matches("[A-Z]+")); 116 } 117 } 118 119 /* Devices launching in R and after must export dynamic-partition. */ 120 @Test testDynamicPartition()121 public void testDynamicPartition() throws Exception { 122 String dynamic_partition = mDevice.getFastbootVariable("dynamic-partition"); 123 CLog.d("dynamic_partition: '%s'", dynamic_partition); 124 assertTrue(dynamic_partition.equals("true")); 125 } 126 127 /* Devices launching in R and after must export treble-enabled. */ 128 @Test testTrebleEnable()129 public void testTrebleEnable() throws Exception { 130 String treble_enabled = mDevice.getFastbootVariable("treble-enabled"); 131 CLog.d("treble_enabled: '%s'", treble_enabled); 132 assertTrue(treble_enabled.equals("true") || treble_enabled.equals("false")); 133 } 134 135 /* Devices launching in R and after must export first-api-level. */ 136 @Test testFirstApiLevel()137 public void testFirstApiLevel() throws Exception { 138 String first_api_level = mDevice.getFastbootVariable("first-api-level"); 139 CLog.d("first_api_level: '%s'", first_api_level); 140 try { 141 int api_level = Integer.parseInt(first_api_level); 142 assertTrue(api_level >= PLATFORM_API_LEVEL_R); 143 } catch (NumberFormatException nfe) { 144 fail("Failed to parse first-api-level: " + first_api_level); 145 } 146 } 147 148 /* Devices launching in R and after must export security-patch-level. */ 149 @Test testSecurityPatchLevel()150 public void testSecurityPatchLevel() throws Exception { 151 String SPL = mDevice.getFastbootVariable("security-patch-level"); 152 CLog.d("SPL: '%s'", SPL); 153 try { 154 SimpleDateFormat template = new SimpleDateFormat("yyyy-MM-dd"); 155 template.parse(SPL); 156 } catch (ParseException e) { 157 fail("Failed to parse security-patch-level: " + SPL); 158 } 159 } 160 161 /* Devices launching in R and after must export system-fingerprint. */ 162 @Test testSystemFingerprint()163 public void testSystemFingerprint() throws Exception { 164 String systemFingerprint = mDevice.getFastbootVariable("system-fingerprint"); 165 CLog.d("system fingerprint: '%s'", systemFingerprint); 166 verifyFingerprint(systemFingerprint); 167 } 168 169 /* Devices launching in R and after must export vendor-fingerprint. */ 170 @Test testVendorFingerprint()171 public void testVendorFingerprint() throws Exception { 172 String vendorFingerprint = mDevice.getFastbootVariable("vendor-fingerprint"); 173 CLog.d("vendor fingerprint: '%s'", vendorFingerprint); 174 verifyFingerprint(vendorFingerprint); 175 } 176 177 /* 178 * Verifies the fingerprint defined in CDD. 179 * https://source.android.com/compatibility/cdd 180 * 181 * The fingerprint should be of format: 182 * $(BRAND)/$(PRODUCT)/$(DEVICE):$(VERSION.RELEASE)/$(ID)/$(VERSION.INCREMENTAL):$(TYPE)/$(TAGS). 183 */ verifyFingerprint(String fingerprint)184 private void verifyFingerprint(String fingerprint) { 185 final HashSet<String> allBuildVariants = 186 new HashSet<String>(Arrays.asList("user", "userdebug", "eng")); 187 188 final HashSet<String> allTags = 189 new HashSet<String>(Arrays.asList("release-keys", "dev-keys", "test-keys")); 190 191 verifyFingerprintStructure(fingerprint); 192 193 String[] fingerprintSegs = fingerprint.split("/"); 194 assertTrue(fingerprintSegs[0].matches("^[a-zA-Z0-9_-]+$")); // BRAND 195 assertTrue(fingerprintSegs[1].matches("^[a-zA-Z0-9_-]+$")); // PRODUCT 196 197 String[] devicePlatform = fingerprintSegs[2].split(":"); 198 assertEquals(2, devicePlatform.length); 199 assertTrue(devicePlatform[0].matches("^[a-zA-Z0-9_-]+$")); // DEVICE 200 201 // Platform version is a letter on pre-release builds, e.g., R, or 202 // is a number on final release # builds, e.g., 11. 203 try { 204 int releaseVersion = Integer.parseInt(devicePlatform[1]); // VERSION.RELEASE 205 assertTrue(releaseVersion >= ANDROID_RELEASE_VERSION_R); 206 } catch (NumberFormatException nfe) { 207 assertTrue(devicePlatform[1].matches("[A-Z]+")); 208 } 209 210 assertTrue(fingerprintSegs[3].matches("^[a-zA-Z0-9._-]+$")); // ID 211 212 String[] buildNumberVariant = fingerprintSegs[4].split(":"); 213 assertTrue(buildNumberVariant[0].matches("^[^ :\\/~]+$")); // VERSION.INCREMENTAL 214 assertTrue(allBuildVariants.contains(buildNumberVariant[1])); // TYPE 215 216 assertTrue(allTags.contains(fingerprintSegs[5])); // TAG 217 } 218 verifyFingerprintStructure(String fingerprint)219 private void verifyFingerprintStructure(String fingerprint) { 220 assertEquals("Build fingerprint must not include whitespace", -1, fingerprint.indexOf(' ')); 221 222 String[] segments = fingerprint.split("/"); 223 assertEquals("Build fingerprint does not match expected format", 6, segments.length); 224 225 String[] devicePlatform = segments[2].split(":"); 226 assertEquals(2, devicePlatform.length); 227 228 assertTrue(segments[4].contains(":")); 229 String buildVariant = segments[4].split(":")[1]; 230 assertTrue(buildVariant.length() > 0); 231 } 232 } 233