blob: 8a3f48efb504cab9c3cd9239c8272f7fbdfe677d [file] [log] [blame]
/*
* 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);
}
}