summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
author Chris Wailes <chriswailes@google.com> 2020-11-30 17:20:38 -0800
committer Chris Wailes <chriswailes@google.com> 2020-12-07 15:25:21 -0800
commit0ef67ee5189747a147d3a63d2d160e9a4ec7c4c4 (patch)
tree1896f84e3c041f1de7635bea5e41e9ac316db761
parentd42204a8655a125fefbdfcd1c10646943d85df54 (diff)
Modify dexopt invocation based on install scenario
This CL implements the logic that modifies the way dexopt is invoked based on the provided installation scenario. Bug: 173137187 Test: build Merged-In: Iab34d79cbbc4fb0d88946ef38a1edcca16cd3a29 Change-Id: Iab34d79cbbc4fb0d88946ef38a1edcca16cd3a29
-rw-r--r--services/core/java/com/android/server/pm/PackageManagerService.java55
-rw-r--r--services/core/java/com/android/server/pm/PackageManagerServiceCompilerMapping.java23
-rw-r--r--services/core/java/com/android/server/pm/dex/ArtManagerService.java39
-rw-r--r--services/core/java/com/android/server/pm/dex/DexManager.java95
-rw-r--r--services/core/java/com/android/server/pm/dex/DexoptOptions.java10
5 files changed, 197 insertions, 25 deletions
diff --git a/services/core/java/com/android/server/pm/PackageManagerService.java b/services/core/java/com/android/server/pm/PackageManagerService.java
index 498e7360bdd7..4630a905b41e 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 class PackageManagerService extends IPackageManager.Stub
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;
@@ -16998,6 +17003,26 @@ public class PackageManagerService extends IPackageManager.Stub
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:
@@ -17018,11 +17043,18 @@ public class PackageManagerService extends IPackageManager.Stub
// 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.
@@ -17033,19 +17065,6 @@ public class PackageManagerService extends IPackageManager.Stub
}
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 5fc5bac0c8c2..9cd55a6bb07e 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 @@ package com.android.server.pm;
import android.os.SystemProperties;
+import com.android.server.pm.dex.DexoptOptions;
+
import dalvik.system.DexFile;
/**
@@ -26,10 +28,22 @@ import dalvik.system.DexFile;
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 @@ public class PackageManagerServiceCompilerMapping {
// 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 a7f30fde703b..6e145b5ecbe4 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 @@ public class ArtManagerService extends android.content.pm.dex.IArtManager.Stub {
// 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 @@ public class ArtManagerService extends android.content.pm.dex.IArtManager.Stub {
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 @@ public class ArtManagerService extends android.content.pm.dex.IArtManager.Stub {
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 3074250950f7..cc6d80a2aeec 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.Context;
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 @@ public class DexManager {
@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 @@ public class DexManager {
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 @@ public class DexManager {
}
}
+ /**
+ * 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 68f38861d7e4..ea233161b4af 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 @@ public final class DexoptOptions {
// 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 @@ public final class DexoptOptions {
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).