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

Commit b11556fc authored by Shubham Ajmera's avatar Shubham Ajmera Committed by android-build-merger
Browse files

Merge "Reduce app size by downgrading inactive apps"

am: 8bcd66d3

Change-Id: I4bfba3f7eb16442a7a69466cf72b22198acde6c4
parents 33569ca4 8bcd66d3
Loading
Loading
Loading
Loading
+1 −1
Original line number Diff line number Diff line
@@ -513,7 +513,7 @@ interface IPackageManager {
     * configuration.
     */
    boolean performDexOpt(String packageName, boolean checkProfiles,
            int compileReason, boolean force, boolean bootComplete);
            int compileReason, boolean force, boolean bootComplete, boolean downgrade);

    /**
     * Ask the package manager to perform a dex-opt with the given compiler filter.
+1 −1
Original line number Diff line number Diff line
@@ -577,7 +577,7 @@ public class ZygoteInit {
                try {
                    installd.dexopt(classPathElement, Process.SYSTEM_UID, packageName,
                            instructionSet, dexoptNeeded, outputPath, dexFlags, compilerFilter,
                            uuid, sharedLibraries, seInfo);
                            uuid, sharedLibraries, seInfo, false /* downgrade */);
                } catch (RemoteException | ServiceSpecificException e) {
                    // Ignore (but log), we need this on the classpath for fallback mode.
                    Log.w(TAG, "Failed compiling classpath element for system server: "
+74 −12
Original line number Diff line number Diff line
@@ -18,7 +18,6 @@ package com.android.server.pm;

import static com.android.server.pm.PackageManagerService.DEBUG_DEXOPT;

import android.app.AlarmManager;
import android.app.job.JobInfo;
import android.app.job.JobParameters;
import android.app.job.JobScheduler;
@@ -40,6 +39,7 @@ import com.android.server.LocalServices;
import com.android.server.PinnerService;

import java.io.File;
import java.util.Set;
import java.util.concurrent.atomic.AtomicBoolean;
import java.util.concurrent.TimeUnit;

@@ -73,6 +73,9 @@ public class BackgroundDexOptService extends JobService {
    // Optimizations should be aborted. No space left on device.
    private static final int OPTIMIZE_ABORT_NO_SPACE_LEFT = 3;

    // Used for calculating space threshold for downgrading unused apps.
    private static final int LOW_THRESHOLD_MULTIPLIER_FOR_DOWNGRADE = 2;

    /**
     * Set of failed packages remembered across job runs.
     */
@@ -92,6 +95,9 @@ public class BackgroundDexOptService extends JobService {

    private final File mDataDir = Environment.getDataDirectory();

    private static final long mDowngradeUnusedAppsThresholdInMillis =
            getDowngradeUnusedAppsThresholdInMillis();

    public static void schedule(Context context) {
        JobScheduler js = (JobScheduler) context.getSystemService(Context.JOB_SCHEDULER_SERVICE);

@@ -215,7 +221,8 @@ public class BackgroundDexOptService extends JobService {
                    /* checkProfiles */ false,
                    PackageManagerService.REASON_BOOT,
                    /* force */ false,
                    /* bootComplete */ true);
                    /* bootComplete */ true,
                    /* downgrade */ false);
            if (result == PackageDexOptimizer.DEX_OPT_PERFORMED)  {
                updatedPackages.add(pkg);
            }
@@ -243,7 +250,8 @@ public class BackgroundDexOptService extends JobService {
    }

    // Optimize the given packages and return the optimization result (one of the OPTIMIZE_* codes).
    private int idleOptimization(PackageManagerService pm, ArraySet<String> pkgs, Context context) {
    private int idleOptimization(PackageManagerService pm, ArraySet<String> pkgs,
            Context context) {
        Log.i(TAG, "Performing idle optimizations");
        // If post-boot update is still running, request that it exits early.
        mExitPostBootUpdate.set(true);
@@ -274,9 +282,16 @@ public class BackgroundDexOptService extends JobService {
            long lowStorageThreshold, boolean is_for_primary_dex,
            ArraySet<String> failedPackageNames) {
        ArraySet<String> updatedPackages = new ArraySet<>();
        Set<String> unusedPackages = pm.getUnusedPackages(mDowngradeUnusedAppsThresholdInMillis);
        // Only downgrade apps when space is low on device.
        // Threshold is selected above the lowStorageThreshold so that we can pro-actively clean
        // up disk before user hits the actual lowStorageThreshold.
        final long lowStorageThresholdForDowngrade = LOW_THRESHOLD_MULTIPLIER_FOR_DOWNGRADE *
                lowStorageThreshold;
        boolean shouldDowngrade = shouldDowngrade(lowStorageThresholdForDowngrade);
        for (String pkg : pkgs) {
            int abort_code = abortIdleOptimizations(lowStorageThreshold);
            if (abort_code != OPTIMIZE_CONTINUE) {
            if (abort_code == OPTIMIZE_ABORT_BY_JOB_SCHEDULER) {
                return abort_code;
            }

@@ -284,11 +299,36 @@ public class BackgroundDexOptService extends JobService {
                if (failedPackageNames.contains(pkg)) {
                    // Skip previously failing package
                    continue;
                }
            }

            int reason;
            boolean downgrade;
            // Downgrade unused packages.
            if (unusedPackages.contains(pkg) && shouldDowngrade) {
                // This applies for system apps or if packages location is not a directory, i.e.
                // monolithic install.
                if (is_for_primary_dex && !pm.canHaveOatDir(pkg)) {
                    // For apps that don't have the oat directory, instead of downgrading,
                    // remove their compiler artifacts from dalvik cache.
                    pm.deleteOatArtifactsOfPackage(pkg);
                    continue;
                } else {
                    // Conservatively add package to the list of failing ones in case performDexOpt
                    // never returns.
                    failedPackageNames.add(pkg);
                    reason = PackageManagerService.REASON_INACTIVE_PACKAGE_DOWNGRADE;
                    downgrade = true;
                }
            } else if (abort_code != OPTIMIZE_ABORT_NO_SPACE_LEFT) {
                reason = PackageManagerService.REASON_BACKGROUND_DEXOPT;
                downgrade = false;
            } else {
                // can't dexopt because of low space.
                continue;
            }

            synchronized (failedPackageNames) {
                // Conservatively add package to the list of failing ones in case
                // performDexOpt never returns.
                failedPackageNames.add(pkg);
            }

            // Optimize package if needed. Note that there can be no race between
@@ -297,17 +337,19 @@ public class BackgroundDexOptService extends JobService {
            if (is_for_primary_dex) {
                int result = pm.performDexOptWithStatus(pkg,
                        /* checkProfiles */ true,
                        PackageManagerService.REASON_BACKGROUND_DEXOPT,
                        /* force */ false,
                        /* bootComplete */ true);
                        reason,
                        false /* forceCompile*/,
                        true /* bootComplete */,
                        downgrade);
                success = result != PackageDexOptimizer.DEX_OPT_FAILED;
                if (result == PackageDexOptimizer.DEX_OPT_PERFORMED) {
                    updatedPackages.add(pkg);
                }
            } else {
                success = pm.performDexOptSecondary(pkg,
                        PackageManagerService.REASON_BACKGROUND_DEXOPT,
                        /* force */ false);
                        reason,
                        false /* force */,
                        downgrade);
            }
            if (success) {
                // Dexopt succeeded, remove package from the list of failing ones.
@@ -347,6 +389,16 @@ public class BackgroundDexOptService extends JobService {
        return OPTIMIZE_CONTINUE;
    }

    // Evaluate whether apps should be downgraded.
    private boolean shouldDowngrade(long lowStorageThresholdForDowngrade) {
        long usableSpace = mDataDir.getUsableSpace();
        if (usableSpace < lowStorageThresholdForDowngrade) {
            return true;
        }

        return false;
    }

    /**
     * Execute the idle optimizations immediately.
     */
@@ -415,4 +467,14 @@ public class BackgroundDexOptService extends JobService {
            pinnerService.update(updatedPackages);
        }
    }

    private static long getDowngradeUnusedAppsThresholdInMillis() {
        final String sysPropKey = "pm.dexopt.downgrade_after_inactive_days";
        String sysPropValue = SystemProperties.get(sysPropKey);
        if (sysPropValue == null || sysPropValue.isEmpty()) {
            Log.w(TAG, "SysProp " + sysPropKey + " not set");
            return Long.MAX_VALUE;
        }
        return TimeUnit.DAYS.toMillis(Long.parseLong(sysPropValue));
    }
}
+2 −2
Original line number Diff line number Diff line
@@ -279,13 +279,13 @@ public class Installer extends SystemService {
    public void dexopt(String apkPath, int uid, @Nullable String pkgName, String instructionSet,
            int dexoptNeeded, @Nullable String outputPath, int dexFlags,
            String compilerFilter, @Nullable String volumeUuid, @Nullable String sharedLibraries,
            @Nullable String seInfo)
            @Nullable String seInfo, boolean downgrade)
            throws InstallerException {
        assertValidInstructionSet(instructionSet);
        if (!checkBeforeRemote()) return;
        try {
            mInstalld.dexopt(apkPath, uid, pkgName, instructionSet, dexoptNeeded, outputPath,
                    dexFlags, compilerFilter, volumeUuid, sharedLibraries, seInfo);
                    dexFlags, compilerFilter, volumeUuid, sharedLibraries, seInfo, downgrade);
        } catch (Exception e) {
            throw InstallerException.from(e);
        }
+9 −7
Original line number Diff line number Diff line
@@ -30,7 +30,6 @@ import android.os.ResultReceiver;
import android.os.ServiceManager;
import android.os.ShellCallback;
import android.os.storage.StorageManager;
import android.text.TextUtils;
import android.util.Log;
import android.util.Slog;

@@ -40,7 +39,6 @@ import com.android.server.pm.Installer.InstallerException;
import java.io.File;
import java.io.FileDescriptor;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Collection;
import java.util.List;
import java.util.concurrent.TimeUnit;
@@ -261,11 +259,12 @@ public class OtaDexoptService extends IOtaDexopt.Stub {
            public void dexopt(String apkPath, int uid, @Nullable String pkgName,
                    String instructionSet, int dexoptNeeded, @Nullable String outputPath,
                    int dexFlags, String compilerFilter, @Nullable String volumeUuid,
                    @Nullable String sharedLibraries, @Nullable String seInfo) throws InstallerException {
                    @Nullable String sharedLibraries, @Nullable String seInfo, boolean downgrade)
                    throws InstallerException {
                final StringBuilder builder = new StringBuilder();

                // The version. Right now it's 2.
                builder.append("2 ");
                // The version. Right now it's 3.
                builder.append("3 ");

                builder.append("dexopt");

@@ -280,6 +279,7 @@ public class OtaDexoptService extends IOtaDexopt.Stub {
                encodeParameter(builder, volumeUuid);
                encodeParameter(builder, sharedLibraries);
                encodeParameter(builder, seInfo);
                encodeParameter(builder, downgrade);

                commands.add(builder.toString());
            }
@@ -319,12 +319,14 @@ public class OtaDexoptService extends IOtaDexopt.Stub {
                getCompilerFilterForReason(compilationReason),
                null /* CompilerStats.PackageStats */,
                mPackageManagerService.getDexManager().isUsedByOtherApps(pkg.packageName),
                true /* bootComplete */);
                true /* bootComplete */,
                false /* downgrade */);

        mPackageManagerService.getDexManager().dexoptSecondaryDex(pkg.packageName,
                getCompilerFilterForReason(compilationReason),
                false /* force */,
                false /* compileOnlySharedDex */);
                false /* compileOnlySharedDex */,
                false /* downgrade */);
        return commands;
    }

Loading