Merge changes from topic "install-hints" am: 21b065b610
Original change: https://android-review.googlesource.com/c/platform/frameworks/base/+/1482838
MUST ONLY BE SUBMITTED BY AUTOMERGER
Change-Id: I0d9a22925b9ea70f06954e57f7ce98a5c3cfd3b1
diff --git a/services/core/java/com/android/server/pm/PackageManagerService.java b/services/core/java/com/android/server/pm/PackageManagerService.java
index 494d9c6..c121d24 100644
--- a/services/core/java/com/android/server/pm/PackageManagerService.java
+++ b/services/core/java/com/android/server/pm/PackageManagerService.java
@@ -677,10 +677,15 @@
public static final int REASON_FIRST_BOOT = 0;
public static final int REASON_BOOT = 1;
public static final int REASON_INSTALL = 2;
- public static final int REASON_BACKGROUND_DEXOPT = 3;
- public static final int REASON_AB_OTA = 4;
- public static final int REASON_INACTIVE_PACKAGE_DOWNGRADE = 5;
- public static final int REASON_SHARED = 6;
+ public static final int REASON_INSTALL_FAST = 3;
+ public static final int REASON_INSTALL_BULK = 4;
+ public static final int REASON_INSTALL_BULK_SECONDARY = 5;
+ public static final int REASON_INSTALL_BULK_DOWNGRADED = 6;
+ public static final int REASON_INSTALL_BULK_SECONDARY_DOWNGRADED = 7;
+ public static final int REASON_BACKGROUND_DEXOPT = 8;
+ public static final int REASON_AB_OTA = 9;
+ public static final int REASON_INACTIVE_PACKAGE_DOWNGRADE = 10;
+ public static final int REASON_SHARED = 11;
public static final int REASON_LAST = REASON_SHARED;
@@ -17006,6 +17011,26 @@
resolveUserIds(reconciledPkg.installArgs.user.getIdentifier()),
/* updateReferenceProfileContent= */ true);
+ // Compute the compilation reason from the installation scenario.
+ final int compilationReason = mDexManager.getCompilationReasonForInstallScenario(
+ reconciledPkg.installArgs.mInstallScenario);
+
+ // Construct the DexoptOptions early to see if we should skip running dexopt.
+ //
+ // Do not run PackageDexOptimizer through the local performDexOpt
+ // method because `pkg` may not be in `mPackages` yet.
+ //
+ // Also, don't fail application installs if the dexopt step fails.
+ final boolean isBackupOrRestore =
+ reconciledPkg.installArgs.installReason == INSTALL_REASON_DEVICE_RESTORE
+ || reconciledPkg.installArgs.installReason == INSTALL_REASON_DEVICE_SETUP;
+
+ final int dexoptFlags = DexoptOptions.DEXOPT_BOOT_COMPLETE
+ | DexoptOptions.DEXOPT_INSTALL_WITH_DEX_METADATA_FILE
+ | (isBackupOrRestore ? DexoptOptions.DEXOPT_FOR_RESTORE : 0);
+ DexoptOptions dexoptOptions =
+ new DexoptOptions(packageName, compilationReason, dexoptFlags);
+
// Check whether we need to dexopt the app.
//
// NOTE: it is IMPORTANT to call dexopt:
@@ -17026,11 +17051,18 @@
// continuous progress to the useur instead of mysteriously blocking somewhere in the
// middle of running an instant app. The default behaviour can be overridden
// via gservices.
+ //
+ // Furthermore, dexopt may be skipped, depending on the install scenario and current
+ // state of the device.
+ //
+ // TODO(b/174695087): instantApp and onIncremental should be removed and their install
+ // path moved to SCENARIO_FAST.
final boolean performDexopt =
(!instantApp || Global.getInt(mContext.getContentResolver(),
Global.INSTANT_APP_DEXOPT_ENABLED, 0) != 0)
&& !pkg.isDebuggable()
- && (!onIncremental);
+ && (!onIncremental)
+ && dexoptOptions.isCompilationEnabled();
if (performDexopt) {
// Compile the layout resources.
@@ -17041,19 +17073,6 @@
}
Trace.traceBegin(TRACE_TAG_PACKAGE_MANAGER, "dexopt");
- // Do not run PackageDexOptimizer through the local performDexOpt
- // method because `pkg` may not be in `mPackages` yet.
- //
- // Also, don't fail application installs if the dexopt step fails.
- int flags = DexoptOptions.DEXOPT_BOOT_COMPLETE
- | DexoptOptions.DEXOPT_INSTALL_WITH_DEX_METADATA_FILE;
- if (reconciledPkg.installArgs.installReason == INSTALL_REASON_DEVICE_RESTORE
- || reconciledPkg.installArgs.installReason == INSTALL_REASON_DEVICE_SETUP) {
- flags |= DexoptOptions.DEXOPT_FOR_RESTORE;
- }
- DexoptOptions dexoptOptions = new DexoptOptions(packageName,
- REASON_INSTALL,
- flags);
ScanResult result = reconciledPkg.scanResult;
// This mirrors logic from commitReconciledScanResultLocked, where the library files
diff --git a/services/core/java/com/android/server/pm/PackageManagerServiceCompilerMapping.java b/services/core/java/com/android/server/pm/PackageManagerServiceCompilerMapping.java
index 5fc5bac..9cd55a6 100644
--- a/services/core/java/com/android/server/pm/PackageManagerServiceCompilerMapping.java
+++ b/services/core/java/com/android/server/pm/PackageManagerServiceCompilerMapping.java
@@ -18,6 +18,8 @@
import android.os.SystemProperties;
+import com.android.server.pm.dex.DexoptOptions;
+
import dalvik.system.DexFile;
/**
@@ -26,10 +28,22 @@
public class PackageManagerServiceCompilerMapping {
// Names for compilation reasons.
public static final String REASON_STRINGS[] = {
- "first-boot", "boot", "install", "bg-dexopt", "ab-ota", "inactive", "shared"
+ "first-boot",
+ "boot",
+ "install",
+ "install-fast",
+ "install-bulk",
+ "install-bulk-secondary",
+ "install-bulk-downgraded",
+ "install-bulk-secondary-downgraded",
+ "bg-dexopt",
+ "ab-ota",
+ "inactive",
+ // "shared" must be the last entry
+ "shared"
};
- static final int REASON_SHARED_INDEX = 6;
+ static final int REASON_SHARED_INDEX = REASON_STRINGS.length - 1;
// Static block to ensure the strings array is of the right length.
static {
@@ -53,8 +67,9 @@
// 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)) {
+ if (sysPropValue == null || sysPropValue.isEmpty()
+ || !(sysPropValue.equals(DexoptOptions.COMPILER_FILTER_NOOP)
+ || DexFile.isValidCompilerFilter(sysPropValue))) {
throw new IllegalStateException("Value \"" + sysPropValue +"\" not valid "
+ "(reason " + REASON_STRINGS[reason] + ")");
} else if (!isFilterAllowedForReason(reason, sysPropValue)) {
diff --git a/services/core/java/com/android/server/pm/dex/ArtManagerService.java b/services/core/java/com/android/server/pm/dex/ArtManagerService.java
index a7f30fd..6e145b5 100644
--- a/services/core/java/com/android/server/pm/dex/ArtManagerService.java
+++ b/services/core/java/com/android/server/pm/dex/ArtManagerService.java
@@ -579,6 +579,8 @@
// Constants used for logging compilation reason to TRON.
// DO NOT CHANGE existing values.
//
+ // In the below constants, the abbreviation DM stands for "DEX metadata".
+ //
// NOTE: '-1' value is reserved for the case where we cannot produce a valid
// PackageOptimizationInfo because the ArtManagerInternal is not ready to be used by the
// ActivityMetricsLoggers.
@@ -591,7 +593,18 @@
private static final int TRON_COMPILATION_REASON_AB_OTA = 6;
private static final int TRON_COMPILATION_REASON_INACTIVE = 7;
private static final int TRON_COMPILATION_REASON_SHARED = 8;
- private static final int TRON_COMPILATION_REASON_INSTALL_WITH_DEX_METADATA = 9;
+ private static final int TRON_COMPILATION_REASON_INSTALL_WITH_DM = 9;
+ private static final int TRON_COMPILATION_REASON_INSTALL_FAST = 10;
+ private static final int TRON_COMPILATION_REASON_INSTALL_BULK = 11;
+ private static final int TRON_COMPILATION_REASON_INSTALL_BULK_SECONDARY = 12;
+ private static final int TRON_COMPILATION_REASON_INSTALL_BULK_DOWNGRADED = 13;
+ private static final int TRON_COMPILATION_REASON_INSTALL_BULK_SECONDARY_DOWNGRADED = 14;
+ private static final int TRON_COMPILATION_REASON_INSTALL_FAST_WITH_DM = 15;
+ private static final int TRON_COMPILATION_REASON_INSTALL_BULK_WITH_DM = 16;
+ private static final int TRON_COMPILATION_REASON_INSTALL_BULK_SECONDARY_WITH_DM = 17;
+ private static final int TRON_COMPILATION_REASON_INSTALL_BULK_DOWNGRADED_WITH_DM = 18;
+ private static final int
+ TRON_COMPILATION_REASON_INSTALL_BULK_SECONDARY_DOWNGRADED_WITH_DM = 19;
// The annotation to add as a suffix to the compilation reason when dexopt was
// performed with dex metadata.
@@ -611,10 +624,30 @@
case "ab-ota" : return TRON_COMPILATION_REASON_AB_OTA;
case "inactive" : return TRON_COMPILATION_REASON_INACTIVE;
case "shared" : return TRON_COMPILATION_REASON_SHARED;
- // This is a special marker for dex metadata installation that does not
+ case "install-fast" :
+ return TRON_COMPILATION_REASON_INSTALL_FAST;
+ case "install-bulk" :
+ return TRON_COMPILATION_REASON_INSTALL_BULK;
+ case "install-bulk-secondary" :
+ return TRON_COMPILATION_REASON_INSTALL_BULK_SECONDARY;
+ case "install-bulk-downgraded" :
+ return TRON_COMPILATION_REASON_INSTALL_BULK_DOWNGRADED;
+ case "install-bulk-secondary-downgraded" :
+ return TRON_COMPILATION_REASON_INSTALL_BULK_SECONDARY_DOWNGRADED;
+ // These are special markers for dex metadata installation that do not
// have an equivalent as a system property.
case "install" + DEXOPT_REASON_WITH_DEX_METADATA_ANNOTATION :
- return TRON_COMPILATION_REASON_INSTALL_WITH_DEX_METADATA;
+ return TRON_COMPILATION_REASON_INSTALL_WITH_DM;
+ case "install-fast" + DEXOPT_REASON_WITH_DEX_METADATA_ANNOTATION :
+ return TRON_COMPILATION_REASON_INSTALL_FAST_WITH_DM;
+ case "install-bulk" + DEXOPT_REASON_WITH_DEX_METADATA_ANNOTATION :
+ return TRON_COMPILATION_REASON_INSTALL_BULK_WITH_DM;
+ case "install-bulk-secondary" + DEXOPT_REASON_WITH_DEX_METADATA_ANNOTATION :
+ return TRON_COMPILATION_REASON_INSTALL_BULK_SECONDARY_WITH_DM;
+ case "install-bulk-downgraded" + DEXOPT_REASON_WITH_DEX_METADATA_ANNOTATION :
+ return TRON_COMPILATION_REASON_INSTALL_BULK_DOWNGRADED_WITH_DM;
+ case "install-bulk-secondary-downgraded" + DEXOPT_REASON_WITH_DEX_METADATA_ANNOTATION :
+ return TRON_COMPILATION_REASON_INSTALL_BULK_SECONDARY_DOWNGRADED_WITH_DM;
default: return TRON_COMPILATION_REASON_UNKNOWN;
}
}
diff --git a/services/core/java/com/android/server/pm/dex/DexManager.java b/services/core/java/com/android/server/pm/dex/DexManager.java
index 3074250..cc6d80a 100644
--- a/services/core/java/com/android/server/pm/dex/DexManager.java
+++ b/services/core/java/com/android/server/pm/dex/DexManager.java
@@ -27,8 +27,11 @@
import android.content.pm.ApplicationInfo;
import android.content.pm.IPackageManager;
import android.content.pm.PackageInfo;
+import android.content.pm.PackageManager;
import android.content.pm.PackagePartitions;
+import android.os.BatteryManager;
import android.os.FileUtils;
+import android.os.PowerManager;
import android.os.RemoteException;
import android.os.SystemProperties;
import android.os.UserHandle;
@@ -107,6 +110,13 @@
@GuardedBy("mInstallLock")
private final Installer mInstaller;
+ private BatteryManager mBatteryManager = null;
+ private PowerManager mPowerManager = null;
+
+ // An integer percentage value used to determine when the device is considered to be on low
+ // power for compilation purposes.
+ private final int mCriticalBatteryLevel;
+
// Possible outcomes of a dex search.
private static int DEX_SEARCH_NOT_FOUND = 0; // dex file not found
private static int DEX_SEARCH_FOUND_PRIMARY = 1; // dex file is the primary/base apk
@@ -123,6 +133,23 @@
mInstaller = installer;
mInstallLock = installLock;
mDynamicCodeLogger = new DynamicCodeLogger(pms, installer);
+
+ // This is currently checked to handle tests that pass in a null context.
+ // TODO(b/174783329): Modify the tests to pass in a mocked Context, PowerManager,
+ // and BatteryManager.
+ if (mContext != null) {
+ mPowerManager = mContext.getSystemService(PowerManager.class);
+
+ if (mPowerManager == null) {
+ Slog.wtf(TAG, "Power Manager is unavailable at time of Dex Manager start");
+ }
+
+ mCriticalBatteryLevel = mContext.getResources().getInteger(
+ com.android.internal.R.integer.config_criticalBatteryWarningLevel);
+ } else {
+ // This value will never be used as the Battery Manager null check will fail first.
+ mCriticalBatteryLevel = 0;
+ }
}
public DynamicCodeLogger getDynamicCodeLogger() {
@@ -905,6 +932,74 @@
}
}
+ /**
+ * Translates install scenarios into compilation reasons. This process can be influenced
+ * by the state of the device.
+ */
+ public int getCompilationReasonForInstallScenario(int installScenario) {
+ // Compute the compilation reason from the installation scenario.
+
+ boolean resourcesAreCritical = areBatteryThermalOrMemoryCritical();
+ switch (installScenario) {
+ case PackageManager.INSTALL_SCENARIO_DEFAULT: {
+ return PackageManagerService.REASON_INSTALL;
+ }
+ case PackageManager.INSTALL_SCENARIO_FAST: {
+ return PackageManagerService.REASON_INSTALL_FAST;
+ }
+ case PackageManager.INSTALL_SCENARIO_BULK: {
+ if (resourcesAreCritical) {
+ return PackageManagerService.REASON_INSTALL_BULK_DOWNGRADED;
+ } else {
+ return PackageManagerService.REASON_INSTALL_BULK;
+ }
+ }
+ case PackageManager.INSTALL_SCENARIO_BULK_SECONDARY: {
+ if (resourcesAreCritical) {
+ return PackageManagerService.REASON_INSTALL_BULK_SECONDARY_DOWNGRADED;
+ } else {
+ return PackageManagerService.REASON_INSTALL_BULK_SECONDARY;
+ }
+ }
+ default: {
+ throw new IllegalArgumentException("Invalid installation scenario");
+ }
+ }
+ }
+
+ /**
+ * Fetches the battery manager object and caches it if it hasn't been fetched already.
+ */
+ private BatteryManager getBatteryManager() {
+ if (mBatteryManager == null) {
+ mBatteryManager = mContext.getSystemService(BatteryManager.class);
+ }
+
+ return mBatteryManager;
+ }
+
+ /**
+ * Returns true if the battery level, device temperature, or memory usage are considered to be
+ * in a critical state.
+ */
+ private boolean areBatteryThermalOrMemoryCritical() {
+ BatteryManager batteryManager = getBatteryManager();
+ boolean isBtmCritical = (batteryManager != null
+ && batteryManager.getIntProperty(BatteryManager.BATTERY_PROPERTY_STATUS)
+ == BatteryManager.BATTERY_STATUS_DISCHARGING
+ && batteryManager.getIntProperty(BatteryManager.BATTERY_PROPERTY_CAPACITY)
+ <= mCriticalBatteryLevel)
+ || (mPowerManager != null
+ && mPowerManager.getCurrentThermalStatus()
+ >= PowerManager.THERMAL_STATUS_SEVERE);
+
+ if (DEBUG) {
+ Log.d(TAG, "Battery, thermal, or memory are critical: " + isBtmCritical);
+ }
+
+ return isBtmCritical;
+ }
+
public static class RegisterDexModuleResult {
public RegisterDexModuleResult() {
this(false, null);
diff --git a/services/core/java/com/android/server/pm/dex/DexoptOptions.java b/services/core/java/com/android/server/pm/dex/DexoptOptions.java
index 68f3886..ea23316 100644
--- a/services/core/java/com/android/server/pm/dex/DexoptOptions.java
+++ b/services/core/java/com/android/server/pm/dex/DexoptOptions.java
@@ -65,6 +65,12 @@
// or device setup and should be scheduled appropriately.
public static final int DEXOPT_FOR_RESTORE = 1 << 11; // TODO(b/135202722): remove
+ /**
+ * A value indicating that dexopt shouldn't be run. This string is only used when loading
+ * filters from the `pm.dexopt.install*` properties and is not propagated to dex2oat.
+ */
+ public static final String COMPILER_FILTER_NOOP = "skip";
+
// The name of package to optimize.
private final String mPackageName;
@@ -176,6 +182,10 @@
return mCompilationReason;
}
+ public boolean isCompilationEnabled() {
+ return !mCompilerFilter.equals(COMPILER_FILTER_NOOP);
+ }
+
/**
* Creates a new set of DexoptOptions which are the same with the exception of the compiler
* filter (set to the given value).