/* * Copyright (C) 2016 The Android Open Source Project * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package com.android.server.pm; import android.os.SystemProperties; import dalvik.system.DexFile; /** * Manage (retrieve) mappings from compilation reason to compilation filter. */ class PackageManagerServiceCompilerMapping { // Names for compilation reasons. static final String REASON_STRINGS[] = { "first-boot", "boot", "install", "bg-dexopt", "ab-ota", "nsys-library", "shared-apk", "forced-dexopt", "core-app" }; // Static block to ensure the strings array is of the right length. static { if (PackageManagerService.REASON_LAST + 1 != REASON_STRINGS.length) { throw new IllegalStateException("REASON_STRINGS not correct"); } } private static String getSystemPropertyName(int reason) { if (reason < 0 || reason >= REASON_STRINGS.length) { throw new IllegalArgumentException("reason " + reason + " invalid"); } return "pm.dexopt." + REASON_STRINGS[reason]; } // Load the property for the given reason and check for validity. This will throw an // exception in case the reason or value are invalid. private static String getAndCheckValidity(int reason) { String sysPropValue = SystemProperties.get(getSystemPropertyName(reason)); if (sysPropValue == null || sysPropValue.isEmpty() || !DexFile.isValidCompilerFilter(sysPropValue)) { throw new IllegalStateException("Value \"" + sysPropValue +"\" not valid " + "(reason " + REASON_STRINGS[reason] + ")"); } // Ensure that some reasons are not mapped to profile-guided filters. switch (reason) { case PackageManagerService.REASON_SHARED_APK: case PackageManagerService.REASON_FORCED_DEXOPT: if (DexFile.isProfileGuidedCompilerFilter(sysPropValue)) { throw new IllegalStateException("\"" + sysPropValue + "\" is profile-guided, " + "but not allowed for " + REASON_STRINGS[reason]); } break; } return sysPropValue; } // Check that the properties are set and valid. // Note: this is done in a separate method so this class can be statically initialized. static void checkProperties() { // We're gonna check all properties and collect the exceptions, so we can give a general // overview. Store the exceptions here. RuntimeException toThrow = null; for (int reason = 0; reason <= PackageManagerService.REASON_LAST; reason++) { try { // Check that the system property name is legal. String sysPropName = getSystemPropertyName(reason); if (sysPropName == null || sysPropName.isEmpty() || sysPropName.length() > SystemProperties.PROP_NAME_MAX) { throw new IllegalStateException("Reason system property name \"" + sysPropName +"\" for reason " + REASON_STRINGS[reason]); } // Check validity, ignore result. getAndCheckValidity(reason); } catch (Exception exc) { if (toThrow == null) { toThrow = new IllegalStateException("PMS compiler filter settings are bad."); } toThrow.addSuppressed(exc); } } if (toThrow != null) { throw toThrow; } } public static String getCompilerFilterForReason(int reason) { return getAndCheckValidity(reason); } /** * Return the compiler filter for "full" compilation. * * We derive that from the traditional "dalvik.vm.dex2oat-filter" property and just make * sure this isn't profile-guided. Returns "speed" in case of invalid (or missing) values. */ public static String getFullCompilerFilter() { String value = SystemProperties.get("dalvik.vm.dex2oat-filter"); if (value == null || value.isEmpty()) { return "speed"; } if (!DexFile.isValidCompilerFilter(value) || DexFile.isProfileGuidedCompilerFilter(value)) { return "speed"; } return value; } /** * Return the non-profile-guided filter corresponding to the given filter. */ public static String getNonProfileGuidedCompilerFilter(String filter) { return DexFile.getNonProfileGuidedCompilerFilter(filter); } }