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