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