Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit c37a01fe authored by Chris Wailes's avatar Chris Wailes
Browse files

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
Change-Id: Iab34d79cbbc4fb0d88946ef38a1edcca16cd3a29
parent 04f2c2d6
Loading
Loading
Loading
Loading
+37 −18
Original line number Diff line number Diff line
@@ -696,10 +696,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;
@@ -17426,6 +17431,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:
@@ -17446,11 +17471,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.
@@ -17461,19 +17493,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
+19 −4
Original line number Diff line number Diff line
@@ -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)) {
+36 −3
Original line number Diff line number Diff line
@@ -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;
        }
    }
+95 −0
Original line number Diff line number Diff line
@@ -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);
+10 −0
Original line number Diff line number Diff line
@@ -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).