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