1 /* 2 * Copyright (C) 2016 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 package com.android.tradefed.util; 17 18 import java.util.HashSet; 19 import java.util.LinkedHashMap; 20 import java.util.LinkedHashSet; 21 import java.util.Map; 22 import java.util.Set; 23 24 /** 25 * Utility class for handling device ABIs 26 */ 27 public class AbiUtils { 28 29 // List of supported abi 30 public static final String ABI_ARM_V7A = "armeabi-v7a"; 31 public static final String ABI_ARM_64_V8A = "arm64-v8a"; 32 public static final String ABI_X86 = "x86"; 33 public static final String ABI_X86_64 = "x86_64"; 34 public static final String ABI_MIPS = "mips"; 35 public static final String ABI_MIPS64 = "mips64"; 36 public static final String ABI_RISCV64 = "riscv64"; 37 38 // List of supported architectures 39 public static final String BASE_ARCH_ARM = "arm"; 40 public static final String ARCH_ARM64 = BASE_ARCH_ARM + "64"; 41 public static final String BASE_ARCH_X86 = "x86"; 42 public static final String ARCH_X86_64 = BASE_ARCH_X86 + "_64"; 43 public static final String BASE_ARCH_MIPS = "mips"; 44 public static final String ARCH_MIPS64 = BASE_ARCH_MIPS + "64"; 45 public static final String ARCH_RISCV64 = "riscv64"; 46 47 /** The set of 32Bit ABIs. */ 48 private static final Set<String> ABIS_32BIT = new LinkedHashSet<String>(); 49 50 /** The set of 64Bit ABIs. */ 51 private static final Set<String> ABIS_64BIT = new LinkedHashSet<String>(); 52 53 /** The set of ARM ABIs. */ 54 protected static final Set<String> ARM_ABIS = new LinkedHashSet<String>(); 55 56 /** The set of Intel ABIs. */ 57 private static final Set<String> INTEL_ABIS = new LinkedHashSet<String>(); 58 59 /** The set of Mips ABIs. */ 60 private static final Set<String> MIPS_ABIS = new LinkedHashSet<String>(); 61 62 /** The set of Risc-V ABIs. */ 63 private static final Set<String> RISCV_ABIS = new LinkedHashSet<String>(); 64 65 /** The set of ABI names which Compatibility supports. */ 66 protected static final Set<String> ABIS_SUPPORTED_BY_COMPATIBILITY = new LinkedHashSet<>(); 67 68 /** The set of Architecture supported. */ 69 private static final Set<String> ARCH_SUPPORTED = new LinkedHashSet<>(); 70 71 /** The map of architecture to ABI. */ 72 private static final Map<String, Set<String>> ARCH_TO_ABIS = 73 new LinkedHashMap<String, Set<String>>(); 74 75 private static final Map<String, String> ABI_TO_ARCH = new LinkedHashMap<String, String>(); 76 77 private static final Map<String, String> ABI_TO_BASE_ARCH = new LinkedHashMap<String, String>(); 78 79 static { 80 ABIS_32BIT.add(ABI_ARM_V7A); 81 ABIS_32BIT.add(ABI_X86); 82 ABIS_32BIT.add(ABI_MIPS); 83 84 ABIS_64BIT.add(ABI_ARM_64_V8A); 85 ABIS_64BIT.add(ABI_X86_64); 86 ABIS_64BIT.add(ABI_MIPS64); 87 ABIS_64BIT.add(ABI_RISCV64); 88 89 ARM_ABIS.add(ABI_ARM_64_V8A); 90 ARM_ABIS.add(ABI_ARM_V7A); 91 92 INTEL_ABIS.add(ABI_X86_64); 93 INTEL_ABIS.add(ABI_X86); 94 95 MIPS_ABIS.add(ABI_MIPS64); 96 MIPS_ABIS.add(ABI_MIPS); 97 98 RISCV_ABIS.add(ABI_RISCV64); 99 ARCH_TO_ABIS.put(BASE_ARCH_ARM, ARM_ABIS)100 ARCH_TO_ABIS.put(BASE_ARCH_ARM, ARM_ABIS); ARCH_TO_ABIS.put(ARCH_ARM64, ARM_ABIS)101 ARCH_TO_ABIS.put(ARCH_ARM64, ARM_ABIS); ARCH_TO_ABIS.put(BASE_ARCH_X86, INTEL_ABIS)102 ARCH_TO_ABIS.put(BASE_ARCH_X86, INTEL_ABIS); ARCH_TO_ABIS.put(ARCH_X86_64, INTEL_ABIS)103 ARCH_TO_ABIS.put(ARCH_X86_64, INTEL_ABIS); ARCH_TO_ABIS.put(BASE_ARCH_MIPS, MIPS_ABIS)104 ARCH_TO_ABIS.put(BASE_ARCH_MIPS, MIPS_ABIS); ARCH_TO_ABIS.put(ARCH_MIPS64, MIPS_ABIS)105 ARCH_TO_ABIS.put(ARCH_MIPS64, MIPS_ABIS); ARCH_TO_ABIS.put(ARCH_RISCV64, RISCV_ABIS)106 ARCH_TO_ABIS.put(ARCH_RISCV64, RISCV_ABIS); 107 108 ABIS_SUPPORTED_BY_COMPATIBILITY.addAll(ARM_ABIS); 109 ABIS_SUPPORTED_BY_COMPATIBILITY.addAll(INTEL_ABIS); 110 ABIS_SUPPORTED_BY_COMPATIBILITY.addAll(MIPS_ABIS); 111 ABIS_SUPPORTED_BY_COMPATIBILITY.addAll(RISCV_ABIS); 112 ABI_TO_ARCH.put(ABI_ARM_V7A, BASE_ARCH_ARM)113 ABI_TO_ARCH.put(ABI_ARM_V7A, BASE_ARCH_ARM); ABI_TO_ARCH.put(ABI_ARM_64_V8A, ARCH_ARM64)114 ABI_TO_ARCH.put(ABI_ARM_64_V8A, ARCH_ARM64); ABI_TO_ARCH.put(ABI_X86, BASE_ARCH_X86)115 ABI_TO_ARCH.put(ABI_X86, BASE_ARCH_X86); ABI_TO_ARCH.put(ABI_X86_64, ARCH_X86_64)116 ABI_TO_ARCH.put(ABI_X86_64, ARCH_X86_64); ABI_TO_ARCH.put(ABI_MIPS, BASE_ARCH_MIPS)117 ABI_TO_ARCH.put(ABI_MIPS, BASE_ARCH_MIPS); ABI_TO_ARCH.put(ABI_MIPS64, ARCH_MIPS64)118 ABI_TO_ARCH.put(ABI_MIPS64, ARCH_MIPS64); ABI_TO_ARCH.put(ABI_RISCV64, ARCH_RISCV64)119 ABI_TO_ARCH.put(ABI_RISCV64, ARCH_RISCV64); 120 ABI_TO_BASE_ARCH.put(ABI_ARM_V7A, BASE_ARCH_ARM)121 ABI_TO_BASE_ARCH.put(ABI_ARM_V7A, BASE_ARCH_ARM); ABI_TO_BASE_ARCH.put(ABI_ARM_64_V8A, BASE_ARCH_ARM)122 ABI_TO_BASE_ARCH.put(ABI_ARM_64_V8A, BASE_ARCH_ARM); ABI_TO_BASE_ARCH.put(ABI_X86, BASE_ARCH_X86)123 ABI_TO_BASE_ARCH.put(ABI_X86, BASE_ARCH_X86); ABI_TO_BASE_ARCH.put(ABI_X86_64, BASE_ARCH_X86)124 ABI_TO_BASE_ARCH.put(ABI_X86_64, BASE_ARCH_X86); ABI_TO_BASE_ARCH.put(ABI_MIPS, BASE_ARCH_MIPS)125 ABI_TO_BASE_ARCH.put(ABI_MIPS, BASE_ARCH_MIPS); ABI_TO_BASE_ARCH.put(ABI_MIPS64, BASE_ARCH_MIPS)126 ABI_TO_BASE_ARCH.put(ABI_MIPS64, BASE_ARCH_MIPS); ABI_TO_BASE_ARCH.put(ABI_RISCV64, ABI_RISCV64)127 ABI_TO_BASE_ARCH.put(ABI_RISCV64, ABI_RISCV64); 128 129 ARCH_SUPPORTED.add(BASE_ARCH_ARM); 130 ARCH_SUPPORTED.add(ARCH_ARM64); 131 ARCH_SUPPORTED.add(BASE_ARCH_X86); 132 ARCH_SUPPORTED.add(ARCH_X86_64); 133 ARCH_SUPPORTED.add(BASE_ARCH_MIPS); 134 ARCH_SUPPORTED.add(ARCH_MIPS64); 135 ARCH_SUPPORTED.add(ARCH_RISCV64); 136 } 137 138 /** 139 * Private constructor to avoid instantiation. 140 */ AbiUtils()141 private AbiUtils() {} 142 143 /** 144 * Returns the set of ABIs associated with the given architecture. 145 * @param arch The architecture to look up. 146 * @return a new Set containing the ABIs. 147 */ getAbisForArch(String arch)148 public static Set<String> getAbisForArch(String arch) { 149 if (arch == null || arch.isEmpty() || !ARCH_TO_ABIS.containsKey(arch)) { 150 return getAbisSupportedByCompatibility(); 151 } 152 return new LinkedHashSet<String>(ARCH_TO_ABIS.get(arch)); 153 } 154 155 /** 156 * Returns the architecture matching the abi. 157 */ getArchForAbi(String abi)158 public static String getArchForAbi(String abi) { 159 if (abi == null || abi.isEmpty()) { 160 throw new IllegalArgumentException("Abi cannot be null or empty"); 161 } 162 return ABI_TO_ARCH.get(abi); 163 } 164 165 /** Returns the base architecture matching the abi. */ getBaseArchForAbi(String abi)166 public static String getBaseArchForAbi(String abi) { 167 if (abi == null || abi.isEmpty()) { 168 throw new IllegalArgumentException("Abi cannot be null or empty"); 169 } 170 return ABI_TO_BASE_ARCH.get(abi); 171 } 172 173 /** 174 * Returns the set of ABIs supported by Compatibility. 175 * 176 * @return a new Set containing the supported ABIs. 177 */ getAbisSupportedByCompatibility()178 public static Set<String> getAbisSupportedByCompatibility() { 179 return new LinkedHashSet<String>(ABIS_SUPPORTED_BY_COMPATIBILITY); 180 } 181 182 /** Returns the set of supported architecture representations. */ getArchSupported()183 public static Set<String> getArchSupported() { 184 return new LinkedHashSet<String>(ARCH_SUPPORTED); 185 } 186 187 /** 188 * @param abi The ABI name to test. 189 * @return true if the given ABI is supported by Compatibility. 190 */ isAbiSupportedByCompatibility(String abi)191 public static boolean isAbiSupportedByCompatibility(String abi) { 192 return ABIS_SUPPORTED_BY_COMPATIBILITY.contains(abi); 193 } 194 195 /** 196 * Creates a flag for the given ABI. 197 * @param abi the ABI to create the flag for. 198 * @return a string which can be add to a command sent to ADB. 199 */ createAbiFlag(String abi)200 public static String createAbiFlag(String abi) { 201 if (abi == null || abi.isEmpty() || !isAbiSupportedByCompatibility(abi)) { 202 return ""; 203 } 204 return String.format("--abi %s ", abi); 205 } 206 207 /** 208 * Creates a unique id from the given ABI and name. 209 * @param abi The ABI to use. 210 * @param name The name to use. 211 * @return a string which uniquely identifies a run. 212 */ createId(String abi, String name)213 public static String createId(String abi, String name) { 214 return String.format("%s %s", abi, name); 215 } 216 217 /** 218 * Parses a unique id into the ABI and name. 219 * @param id The id to parse. 220 * @return a string array containing the ABI and name. 221 */ parseId(String id)222 public static String[] parseId(String id) { 223 if (id == null || !id.contains(" ")) { 224 return new String[] {"", ""}; 225 } 226 return id.split(" "); 227 } 228 229 /** 230 * @return the test name portion of the test id. 231 * e.g. armeabi-v7a android.mytest = android.mytest 232 */ parseTestName(String id)233 public static String parseTestName(String id) { 234 return parseId(id)[1]; 235 } 236 237 /** 238 * @return the abi portion of the test id. 239 * e.g. armeabi-v7a android.mytest = armeabi-v7a 240 */ parseAbi(String id)241 public static String parseAbi(String id) { 242 return parseId(id)[0]; 243 } 244 245 /** 246 * @param abi The name of the ABI. 247 * @return The bitness of the ABI with the given name 248 */ getBitness(String abi)249 public static String getBitness(String abi) { 250 return ABIS_32BIT.contains(abi) ? "32" : "64"; 251 } 252 253 /** 254 * @param unsupportedAbiDescription A comma separated string containing abis. 255 * @return A List of Strings containing valid ABIs. 256 */ parseAbiList(String unsupportedAbiDescription)257 public static Set<String> parseAbiList(String unsupportedAbiDescription) { 258 Set<String> abiSet = new HashSet<>(); 259 String[] descSegments = unsupportedAbiDescription.split(":"); 260 if (descSegments.length == 2) { 261 for (String abi : descSegments[1].split(",")) { 262 String trimmedAbi = abi.trim(); 263 if (isAbiSupportedByCompatibility(trimmedAbi)) { 264 abiSet.add(trimmedAbi); 265 } 266 } 267 } 268 return abiSet; 269 } 270 271 /** 272 * @param abiListProp A comma separated list containing abis coming from the device property. 273 * @return A List of Strings containing valid ABIs. 274 */ parseAbiListFromProperty(String abiListProp)275 public static Set<String> parseAbiListFromProperty(String abiListProp) { 276 Set<String> abiSet = new HashSet<>(); 277 if (abiListProp == null) { 278 return abiSet; 279 } 280 String[] abiList = abiListProp.split(","); 281 for (String abi : abiList) { 282 String trimmedAbi = abi.trim(); 283 if (isAbiSupportedByCompatibility(trimmedAbi)) { 284 abiSet.add(trimmedAbi); 285 } 286 } 287 return abiSet; 288 } 289 290 /** Returns the Set of abis supported by the host machine. */ getHostAbi()291 public static Set<String> getHostAbi() { 292 CommandResult commandResult = RunUtil.getDefault().runTimedCmd(5000L, "uname", "-m"); 293 String mainAbi = commandResult.getStdout().trim(); 294 return getAbisForArch(mainAbi); 295 } 296 } 297