1 /*
2  * Copyright (C) 2015 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.server.pm;
18 
19 import android.content.pm.ApplicationInfo;
20 import android.os.Build;
21 import android.os.SystemProperties;
22 import android.text.TextUtils;
23 import android.util.ArraySet;
24 
25 import dalvik.system.VMRuntime;
26 
27 import java.util.ArrayList;
28 import java.util.List;
29 
30 /**
31  * Provides various methods for obtaining and converting of instruction sets.
32  *
33  * @hide
34  */
35 public class InstructionSets {
36     private static final String PREFERRED_INSTRUCTION_SET =
37             VMRuntime.getInstructionSet(Build.SUPPORTED_ABIS[0]);
getAppDexInstructionSets(ApplicationInfo info)38     public static String[] getAppDexInstructionSets(ApplicationInfo info) {
39         if (info.primaryCpuAbi != null) {
40             if (info.secondaryCpuAbi != null) {
41                 return new String[] {
42                         VMRuntime.getInstructionSet(info.primaryCpuAbi),
43                         VMRuntime.getInstructionSet(info.secondaryCpuAbi) };
44             } else {
45                 return new String[] {
46                         VMRuntime.getInstructionSet(info.primaryCpuAbi) };
47             }
48         }
49 
50         return new String[] { getPreferredInstructionSet() };
51     }
52 
getAppDexInstructionSets(PackageSetting ps)53     public static String[] getAppDexInstructionSets(PackageSetting ps) {
54         if (ps.primaryCpuAbiString != null) {
55             if (ps.secondaryCpuAbiString != null) {
56                 return new String[] {
57                         VMRuntime.getInstructionSet(ps.primaryCpuAbiString),
58                         VMRuntime.getInstructionSet(ps.secondaryCpuAbiString) };
59             } else {
60                 return new String[] {
61                         VMRuntime.getInstructionSet(ps.primaryCpuAbiString) };
62             }
63         }
64 
65         return new String[] { getPreferredInstructionSet() };
66     }
67 
getPreferredInstructionSet()68     public static String getPreferredInstructionSet() {
69         return PREFERRED_INSTRUCTION_SET;
70     }
71 
72     /**
73      * Returns the instruction set that should be used to compile dex code. In the presence of
74      * a native bridge this might be different than the one shared libraries use.
75      */
getDexCodeInstructionSet(String sharedLibraryIsa)76     public static String getDexCodeInstructionSet(String sharedLibraryIsa) {
77         // TODO b/19550105 Build mapping once instead of querying each time
78         String dexCodeIsa = SystemProperties.get("ro.dalvik.vm.isa." + sharedLibraryIsa);
79         return TextUtils.isEmpty(dexCodeIsa) ? sharedLibraryIsa : dexCodeIsa;
80     }
81 
getDexCodeInstructionSets(String[] instructionSets)82     public static String[] getDexCodeInstructionSets(String[] instructionSets) {
83         ArraySet<String> dexCodeInstructionSets = new ArraySet<String>(instructionSets.length);
84         for (String instructionSet : instructionSets) {
85             dexCodeInstructionSets.add(getDexCodeInstructionSet(instructionSet));
86         }
87         return dexCodeInstructionSets.toArray(new String[dexCodeInstructionSets.size()]);
88     }
89 
90     /**
91      * Returns deduplicated list of supported instructions for dex code.
92      */
getAllDexCodeInstructionSets()93     public static String[] getAllDexCodeInstructionSets() {
94         String[] supportedInstructionSets = new String[Build.SUPPORTED_ABIS.length];
95         for (int i = 0; i < supportedInstructionSets.length; i++) {
96             String abi = Build.SUPPORTED_ABIS[i];
97             supportedInstructionSets[i] = VMRuntime.getInstructionSet(abi);
98         }
99         return getDexCodeInstructionSets(supportedInstructionSets);
100     }
101 
getAllInstructionSets()102     public static List<String> getAllInstructionSets() {
103         final String[] allAbis = Build.SUPPORTED_ABIS;
104         final List<String> allInstructionSets = new ArrayList<String>(allAbis.length);
105 
106         for (String abi : allAbis) {
107             final String instructionSet = VMRuntime.getInstructionSet(abi);
108             if (!allInstructionSets.contains(instructionSet)) {
109                 allInstructionSets.add(instructionSet);
110             }
111         }
112 
113         return allInstructionSets;
114     }
115 
116     /**
117      * Calculates the primary instruction set based on the computed Abis of a given package.
118      */
getPrimaryInstructionSet(PackageAbiHelper.Abis abis)119     public static String getPrimaryInstructionSet(PackageAbiHelper.Abis abis) {
120         if (abis.primary == null) {
121             return getPreferredInstructionSet();
122         }
123 
124         return VMRuntime.getInstructionSet(abis.primary);
125     }
126 
127 }
128