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
17package com.android.server.pm;
18
19import android.content.pm.ApplicationInfo;
20import android.os.Build;
21import android.os.SystemProperties;
22import android.text.TextUtils;
23import android.util.ArraySet;
24
25import java.util.ArrayList;
26import java.util.List;
27
28import dalvik.system.VMRuntime;
29
30/**
31 * Provides various methods for obtaining and converting of instruction sets.
32 *
33 * @hide
34 */
35public class InstructionSets {
36    private static final String PREFERRED_INSTRUCTION_SET =
37            VMRuntime.getInstructionSet(Build.SUPPORTED_ABIS[0]);
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
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
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     */
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
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     */
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
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    public static String getPrimaryInstructionSet(ApplicationInfo info) {
117        if (info.primaryCpuAbi == null) {
118            return getPreferredInstructionSet();
119        }
120
121        return VMRuntime.getInstructionSet(info.primaryCpuAbi);
122    }
123
124}
125