PackageManagerServiceCompilerMapping.java revision bdd30d86ef98456161069d11481b2ccd25a11b4e
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
17package com.android.server.pm;
18
19import android.os.SystemProperties;
20
21import dalvik.system.DexFile;
22
23/**
24 * Manage (retrieve) mappings from compilation reason to compilation filter.
25 */
26class PackageManagerServiceCompilerMapping {
27    // Compilation reasons.
28    public static final int REASON_BOOT = 0;
29    public static final int REASON_INSTALL = 1;
30    public static final int REASON_BACKGROUND_DEXOPT = 2;
31    public static final int REASON_AB_OTA = 3;
32    public static final int REASON_NON_SYSTEM_LIBRARY = 4;
33    public static final int REASON_SHARED_APK = 5;
34    public static final int REASON_FORCED_DEXOPT = 6;
35
36    private static final int REASON_LAST = REASON_FORCED_DEXOPT;
37
38    // Names for compilation reasons.
39    static final String REASON_STRINGS[] = {
40            "boot", "install", "bg-dexopt", "ab-ota", "nsys-library", "shared-apk", "forced-dexopt"
41    };
42
43    // Static block to ensure the strings array is of the right length.
44    static {
45        if (REASON_LAST + 1 != REASON_STRINGS.length) {
46            throw new IllegalStateException("REASON_STRINGS not correct");
47        }
48    }
49
50    private static String getSystemPropertyName(int reason) {
51        if (reason < 0 || reason >= REASON_STRINGS.length) {
52            throw new IllegalArgumentException("reason " + reason + " invalid");
53        }
54
55        return "pm.dexopt." + REASON_STRINGS[reason];
56    }
57
58    // Load the property for the given reason and check for validity. This will throw an
59    // exception in case the reason or value are invalid.
60    private static String getAndCheckValidity(int reason) {
61        String sysPropValue = SystemProperties.get(getSystemPropertyName(reason));
62        if (sysPropValue == null || sysPropValue.isEmpty() ||
63                !DexFile.isValidCompilerFilter(sysPropValue)) {
64            throw new IllegalStateException("Value \"" + sysPropValue +"\" not valid "
65                    + "(reason " + REASON_STRINGS[reason] + ")");
66        }
67
68        // Ensure that some reasons are not mapped to profile-guided filters.
69        switch (reason) {
70            case REASON_SHARED_APK:
71            case REASON_FORCED_DEXOPT:
72                if (DexFile.isProfileGuidedCompilerFilter(sysPropValue)) {
73                    throw new IllegalStateException("\"" + sysPropValue + "\" is profile-guided, "
74                            + "but not allowed for " + REASON_STRINGS[reason]);
75                }
76                break;
77        }
78
79        return sysPropValue;
80    }
81
82    // Check that the properties are set and valid.
83    // Note: this is done in a separate method so this class can be statically initialized.
84    static void checkProperties() {
85        // We're gonna check all properties and collect the exceptions, so we can give a general
86        // overview. Store the exceptions here.
87        RuntimeException toThrow = null;
88
89        for (int reason = 0; reason <= REASON_LAST; reason++) {
90            try {
91                // Check that the system property name is legal.
92                String sysPropName = getSystemPropertyName(reason);
93                if (sysPropName == null ||
94                        sysPropName.isEmpty() ||
95                        sysPropName.length() > SystemProperties.PROP_NAME_MAX) {
96                    throw new IllegalStateException("Reason system property name \"" +
97                            sysPropName +"\" for reason " + REASON_STRINGS[reason]);
98                }
99
100                // Check validity, ignore result.
101                getAndCheckValidity(reason);
102            } catch (Exception exc) {
103                if (toThrow == null) {
104                    toThrow = new IllegalStateException("PMS compiler filter settings are bad.");
105                }
106                toThrow.addSuppressed(exc);
107            }
108        }
109
110        if (toThrow != null) {
111            throw toThrow;
112        }
113    }
114
115    public static String getCompilerFilterForReason(int reason) {
116        return getAndCheckValidity(reason);
117    }
118
119    /**
120     * Return the compiler filter for "full" compilation.
121     *
122     * We derive that from the traditional "dalvik.vm.dex2oat-filter" property and just make
123     * sure this isn't profile-guided. Returns "speed" in case of invalid (or missing) values.
124     */
125    public static String getFullCompilerFilter() {
126        String value = SystemProperties.get("dalvik.vm.dex2oat-filter");
127        if (value == null || value.isEmpty()) {
128            return "speed";
129        }
130
131        if (!DexFile.isValidCompilerFilter(value) ||
132                DexFile.isProfileGuidedCompilerFilter(value)) {
133            return "speed";
134        }
135
136        return value;
137    }
138
139}
140