1 /*
2  * Copyright (C) 2014 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.compatibility.common.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     /**
29      * The set of 32Bit ABIs.
30      */
31     private static final Set<String> ABIS_32BIT = new HashSet<String>();
32 
33     /**
34      * The set of 64Bit ABIs.
35      */
36     private static final Set<String> ABIS_64BIT = new HashSet<String>();
37 
38     /**
39      * The set of ARM ABIs.
40      */
41     private static final Set<String> ARM_ABIS = new HashSet<String>();
42 
43     /**
44      * The set of Intel ABIs.
45      */
46     private static final Set<String> INTEL_ABIS = new HashSet<String>();
47 
48     /**
49      * The set of Mips ABIs.
50      */
51     private static final Set<String> MIPS_ABIS = new HashSet<String>();
52 
53     /**
54      * The set of ABI names which Compatibility supports.
55      */
56     private static final Set<String> ABIS_SUPPORTED_BY_COMPATIBILITY = new HashSet<String>();
57 
58     /**
59      * The map of architecture to ABI.
60      */
61     private static final Map<String, Set<String>> ARCH_TO_ABIS = new HashMap<String, Set<String>>();
62     static {
63         ABIS_32BIT.add("armeabi-v7a");
64         ABIS_32BIT.add("x86");
65         ABIS_32BIT.add("mips");
66 
67         ABIS_64BIT.add("arm64-v8a");
68         ABIS_64BIT.add("x86_64");
69         ABIS_64BIT.add("mips64");
70 
71         ARM_ABIS.add("armeabi-v7a");
72         ARM_ABIS.add("arm64-v8a");
73 
74         INTEL_ABIS.add("x86");
75         INTEL_ABIS.add("x86_64");
76 
77         MIPS_ABIS.add("mips");
78         MIPS_ABIS.add("mips64");
79 
80         ARCH_TO_ABIS.put("arm", ARM_ABIS);
81         ARCH_TO_ABIS.put("arm64", ARM_ABIS);
82         ARCH_TO_ABIS.put("x86", INTEL_ABIS);
83         ARCH_TO_ABIS.put("x86_64", INTEL_ABIS);
84         ARCH_TO_ABIS.put("mips", MIPS_ABIS);
85         ARCH_TO_ABIS.put("mips64", MIPS_ABIS);
86 
87         ABIS_SUPPORTED_BY_COMPATIBILITY.addAll(ARM_ABIS);
88         ABIS_SUPPORTED_BY_COMPATIBILITY.addAll(INTEL_ABIS);
89         ABIS_SUPPORTED_BY_COMPATIBILITY.addAll(MIPS_ABIS);
90     }
91 
92     /**
93      * Private constructor to avoid instantiation.
94      */
AbiUtils()95     private AbiUtils() {}
96 
97     /**
98      * Returns the set of ABIs associated with the given architecture.
99      * @param arch The architecture to look up.
100      * @return a new Set containing the ABIs.
101      */
getAbisForArch(String arch)102     public static Set<String> getAbisForArch(String arch) {
103         if (arch == null || arch.isEmpty() || !ARCH_TO_ABIS.containsKey(arch)) {
104             return getAbisSupportedByCompatibility();
105         }
106         return new HashSet<String>(ARCH_TO_ABIS.get(arch));
107     }
108 
109     /**
110      * Returns the set of ABIs supported by Compatibility.
111      * @return a new Set containing the supported ABIs.
112      */
getAbisSupportedByCompatibility()113     public static Set<String> getAbisSupportedByCompatibility() {
114         return new HashSet<String>(ABIS_SUPPORTED_BY_COMPATIBILITY);
115     }
116 
117     /**
118      * @param abi The ABI name to test.
119      * @return true if the given ABI is supported by Compatibility.
120      */
isAbiSupportedByCompatibility(String abi)121     public static boolean isAbiSupportedByCompatibility(String abi) {
122         return ABIS_SUPPORTED_BY_COMPATIBILITY.contains(abi);
123     }
124 
125     /**
126      * Creates a flag for the given ABI.
127      * @param abi the ABI to create the flag for.
128      * @return a string which can be add to a command sent to ADB.
129      */
createAbiFlag(String abi)130     public static String createAbiFlag(String abi) {
131         if (abi == null || abi.isEmpty() || !isAbiSupportedByCompatibility(abi)) {
132             return "";
133         }
134         return String.format("--abi %s ", abi);
135     }
136 
137     /**
138      * Creates a unique id from the given ABI and name.
139      * @param abi The ABI to use.
140      * @param name The name to use.
141      * @return a string which uniquely identifies a run.
142      */
createId(String abi, String name)143     public static String createId(String abi, String name) {
144         return String.format("%s %s", abi, name);
145     }
146 
147     /**
148      * Parses a unique id into the ABI and name.
149      * @param id The id to parse.
150      * @return a string array containing the ABI and name.
151      */
parseId(String id)152     public static String[] parseId(String id) {
153         if (id == null || !id.contains(" ")) {
154             return new String[] {"", ""};
155         }
156         return id.split(" ");
157     }
158 
159     /**
160      * @return the test name portion of the test id.
161      *         e.g. armeabi-v7a android.mytest = android.mytest
162      */
parseTestName(String id)163     public static String parseTestName(String id) {
164         return parseId(id)[1];
165     }
166 
167     /**
168      * @return the abi portion of the test id.
169      *         e.g. armeabi-v7a android.mytest = armeabi-v7a
170      */
parseAbi(String id)171     public static String parseAbi(String id) {
172         return parseId(id)[0];
173     }
174 
175     /**
176      * @param name The name of the ABI.
177      * @return The bitness of the ABI with the given name
178      */
getBitness(String name)179     public static String getBitness(String name) {
180         return ABIS_32BIT.contains(name) ? "32" : "64";
181     }
182 
183     /**
184      * @param unsupportedAbiDescription A comma separated string containing abis.
185      * @return A List of Strings containing valid ABIs.
186      */
parseAbiList(String unsupportedAbiDescription)187     public static Set<String> parseAbiList(String unsupportedAbiDescription) {
188         Set<String> abiSet = new HashSet<>();
189         String[] descSegments = unsupportedAbiDescription.split(":");
190         if (descSegments.length == 2) {
191             for (String abi : descSegments[1].split(",")) {
192                 String trimmedAbi = abi.trim();
193                 if (isAbiSupportedByCompatibility(trimmedAbi)) {
194                     abiSet.add(trimmedAbi);
195                 }
196             }
197         }
198         return abiSet;
199     }
200 }
201