• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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 
17 package com.android.server.pm;
18 
19 import android.os.SystemProperties;
20 
21 import com.android.server.pm.dex.DexoptOptions;
22 
23 import dalvik.system.DexFile;
24 
25 /**
26  * Manage (retrieve) mappings from compilation reason to compilation filter.
27  */
28 public class PackageManagerServiceCompilerMapping {
29     // Names for compilation reasons.
30     public static final String REASON_STRINGS[] = {
31         "first-boot",
32         "boot-after-ota",
33         "post-boot",
34         "install",
35         "install-fast",
36         "install-bulk",
37         "install-bulk-secondary",
38         "install-bulk-downgraded",
39         "install-bulk-secondary-downgraded",
40         "bg-dexopt",
41         "ab-ota",
42         "inactive",
43         "cmdline",
44         // "shared" must be the last entry
45         "shared"
46     };
47 
48     static final int REASON_SHARED_INDEX = REASON_STRINGS.length - 1;
49 
50     // Static block to ensure the strings array is of the right length.
51     static {
52         if (PackageManagerService.REASON_LAST + 1 != REASON_STRINGS.length) {
53             throw new IllegalStateException("REASON_STRINGS not correct");
54         }
55         if (!"shared".equals(REASON_STRINGS[REASON_SHARED_INDEX])) {
56             throw new IllegalStateException("REASON_STRINGS not correct because of shared index");
57         }
58     }
59 
getSystemPropertyName(int reason)60     private static String getSystemPropertyName(int reason) {
61         if (reason < 0 || reason >= REASON_STRINGS.length) {
62             throw new IllegalArgumentException("reason " + reason + " invalid");
63         }
64 
65         return "pm.dexopt." + REASON_STRINGS[reason];
66     }
67 
68     // Load the property for the given reason and check for validity. This will throw an
69     // exception in case the reason or value are invalid.
getAndCheckValidity(int reason)70     private static String getAndCheckValidity(int reason) {
71         String sysPropValue = SystemProperties.get(getSystemPropertyName(reason));
72         if (sysPropValue == null || sysPropValue.isEmpty()
73                 || !(sysPropValue.equals(DexoptOptions.COMPILER_FILTER_NOOP)
74                         || DexFile.isValidCompilerFilter(sysPropValue))) {
75             throw new IllegalStateException("Value \"" + sysPropValue +"\" not valid "
76                     + "(reason " + REASON_STRINGS[reason] + ")");
77         } else if (!isFilterAllowedForReason(reason, sysPropValue)) {
78             throw new IllegalStateException("Value \"" + sysPropValue +"\" not allowed "
79                     + "(reason " + REASON_STRINGS[reason] + ")");
80         }
81 
82         return sysPropValue;
83     }
84 
isFilterAllowedForReason(int reason, String filter)85     private static boolean isFilterAllowedForReason(int reason, String filter) {
86         return reason != REASON_SHARED_INDEX || !DexFile.isProfileGuidedCompilerFilter(filter);
87     }
88 
89     // Check that the properties are set and valid.
90     // Note: this is done in a separate method so this class can be statically initialized.
checkProperties()91     static void checkProperties() {
92         // We're gonna check all properties and collect the exceptions, so we can give a general
93         // overview. Store the exceptions here.
94         RuntimeException toThrow = null;
95 
96         for (int reason = 0; reason <= PackageManagerService.REASON_LAST; reason++) {
97             try {
98                 // Check that the system property name is legal.
99                 String sysPropName = getSystemPropertyName(reason);
100                 if (sysPropName == null || sysPropName.isEmpty()) {
101                     throw new IllegalStateException("Reason system property name \"" +
102                             sysPropName +"\" for reason " + REASON_STRINGS[reason]);
103                 }
104 
105                 // Check validity, ignore result.
106                 getAndCheckValidity(reason);
107             } catch (Exception exc) {
108                 if (toThrow == null) {
109                     toThrow = new IllegalStateException("PMS compiler filter settings are bad.");
110                 }
111                 toThrow.addSuppressed(exc);
112             }
113         }
114 
115         if (toThrow != null) {
116             throw toThrow;
117         }
118     }
119 
getCompilerFilterForReason(int reason)120     public static String getCompilerFilterForReason(int reason) {
121         return getAndCheckValidity(reason);
122     }
123 
124     /**
125      * Return the default compiler filter for compilation.
126      *
127      * We derive that from the traditional "dalvik.vm.dex2oat-filter" property and just make
128      * sure this isn't profile-guided. Returns "speed" in case of invalid (or missing) values.
129      */
getDefaultCompilerFilter()130     public static String getDefaultCompilerFilter() {
131         String value = SystemProperties.get("dalvik.vm.dex2oat-filter");
132         if (value == null || value.isEmpty()) {
133             return "speed";
134         }
135 
136         if (!DexFile.isValidCompilerFilter(value) ||
137                 DexFile.isProfileGuidedCompilerFilter(value)) {
138             return "speed";
139         }
140 
141         return value;
142     }
143 
getReasonName(int reason)144     public static String getReasonName(int reason) {
145         if (reason < 0 || reason >= REASON_STRINGS.length) {
146             throw new IllegalArgumentException("reason " + reason + " invalid");
147         }
148         return REASON_STRINGS[reason];
149     }
150 }
151