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

Commit 493411ac authored by David Brazdil's avatar David Brazdil
Browse files

Add 'package compile' shell command

Bug: 26707406
Change-Id: I554969c9f3b3153179370d3d23a88fa7e8693885
parent b61437de
Loading
Loading
Loading
Loading
+3 −0
Original line number Diff line number Diff line
@@ -452,6 +452,9 @@ interface IPackageManager {
     */
    boolean performDexOptIfNeeded(String packageName, String instructionSet);

    boolean performDexOpt(String packageName, String instructionSet, boolean useProfiles,
            boolean extractOnly, boolean force);

    void forceDexOpt(String packageName);

    /**
+1 −1
Original line number Diff line number Diff line
@@ -94,7 +94,7 @@ public class BackgroundDexOptService extends JobService {
                        continue;
                    }
                    if (!pm.performDexOpt(pkg, /* instruction set */ null, useJitProfiles,
                            /* extractOnly */ false)) {
                            /* extractOnly */ false, /* force */ false)) {
                        // there was a problem running dexopt,
                        // remember this so we do not keep retrying.
                        sFailedPackageNames.add(pkg);
+24 −20
Original line number Diff line number Diff line
@@ -81,7 +81,7 @@ final class PackageDexOptimizer {
     * {@link PackageManagerService#mInstallLock}.
     */
    int performDexOpt(PackageParser.Package pkg, String[] instructionSets,
            boolean inclDependencies, boolean useProfiles, boolean extractOnly) {
            boolean inclDependencies, boolean useProfiles, boolean extractOnly, boolean force) {
        ArraySet<String> done;
        if (inclDependencies && (pkg.usesLibraries != null || pkg.usesOptionalLibraries != null)) {
            done = new ArraySet<String>();
@@ -97,7 +97,7 @@ final class PackageDexOptimizer {
            }
            try {
                return performDexOptLI(pkg, instructionSets, done, useProfiles,
                        extractOnly);
                        extractOnly, force);
            } finally {
                if (useLock) {
                    mDexoptWakeLock.release();
@@ -107,7 +107,7 @@ final class PackageDexOptimizer {
    }

    private int performDexOptLI(PackageParser.Package pkg, String[] targetInstructionSets,
            ArraySet<String> done, boolean useProfiles, boolean extractOnly) {
            ArraySet<String> done, boolean useProfiles, boolean extractOnly, boolean force) {
        final String[] instructionSets = targetInstructionSets != null ?
                targetInstructionSets : getAppDexInstructionSets(pkg.applicationInfo);

@@ -128,17 +128,26 @@ final class PackageDexOptimizer {
        final boolean vmSafeMode = (pkg.applicationInfo.flags & ApplicationInfo.FLAG_VM_SAFE_MODE) != 0;
        final boolean debuggable = (pkg.applicationInfo.flags & ApplicationInfo.FLAG_DEBUGGABLE) != 0;

        if (useProfiles) {
            // If we do a profile guided compilation then we might recompile
            // the same package if more profile information is available.
            force = true;
        }

        final List<String> paths = pkg.getAllCodePathsExcludingResourceOnly();
        boolean performedDexOpt = false;
        final String[] dexCodeInstructionSets = getDexCodeInstructionSets(instructionSets);
        for (String dexCodeInstructionSet : dexCodeInstructionSets) {
            if (!useProfiles && pkg.mDexOptPerformed.contains(dexCodeInstructionSet)) {
                // Skip only if we do not use profiles since they might trigger a recompilation.
            if (!force && pkg.mDexOptPerformed.contains(dexCodeInstructionSet)) {
                continue;
            }

            for (String path : paths) {
                int dexoptNeeded;

                if (force) {
                    dexoptNeeded = DexFile.DEX2OAT_NEEDED;
                } else {
                    try {
                        dexoptNeeded = DexFile.getDexOptNeeded(path, pkg.packageName,
                                dexCodeInstructionSet, /* defer */false);
@@ -146,17 +155,12 @@ final class PackageDexOptimizer {
                        Slog.w(TAG, "IOException reading apk: " + path, ioe);
                        return DEX_OPT_FAILED;
                    }
                }

                if (dexoptNeeded == DexFile.NO_DEXOPT_NEEDED) {
                    if (useProfiles) {
                        // If we do a profile guided compilation then we might recompile the same
                        // package if more profile information is available.
                        dexoptNeeded = DexFile.DEX2OAT_NEEDED;
                    } else {
                    // No dexopt needed and we don't use profiles. Nothing to do.
                    continue;
                }
                }
                final String dexoptType;
                String oatDir = null;
                if (dexoptNeeded == DexFile.DEX2OAT_NEEDED) {
@@ -252,7 +256,7 @@ final class PackageDexOptimizer {
                // TODO: Analyze and investigate if we (should) profile libraries.
                // Currently this will do a full compilation of the library.
                performDexOptLI(libPkg, instructionSets, done, /*useProfiles*/ false,
                        /* extractOnly */ false);
                        /* extractOnly */ false, /* force */ false);
            }
        }
    }
+13 −11
Original line number Diff line number Diff line
@@ -6633,7 +6633,7 @@ public class PackageManagerService extends IPackageManager.Stub {
            if (pkgs != null) {
                for (String pkg : pkgs) {
                    performDexOpt(pkg, null /* instructionSet */, false /* useProfiles */,
                            true /* extractOnly */);
                            true /* extractOnly */, false /* force */);
                }
            }
        }
@@ -6670,26 +6670,28 @@ public class PackageManagerService extends IPackageManager.Stub {
    @Override
    public boolean performDexOptIfNeeded(String packageName, String instructionSet) {
        return performDexOptTraced(packageName, instructionSet, false /* useProfiles */,
                false /* extractOnly */);
                false /* extractOnly */, false /* force */);
    }
    @Override
    public boolean performDexOpt(String packageName, String instructionSet, boolean useProfiles,
            boolean extractOnly) {
        return performDexOptTraced(packageName, instructionSet, useProfiles, extractOnly);
            boolean extractOnly, boolean force) {
        return performDexOptTraced(packageName, instructionSet, useProfiles, extractOnly, force);
    }
    private boolean performDexOptTraced(String packageName, String instructionSet,
                boolean useProfiles, boolean extractOnly) {
                boolean useProfiles, boolean extractOnly, boolean force) {
        Trace.traceBegin(TRACE_TAG_PACKAGE_MANAGER, "dexopt");
        try {
            return performDexOptInternal(packageName, instructionSet, useProfiles, extractOnly);
            return performDexOptInternal(packageName, instructionSet, useProfiles, extractOnly,
                    force);
        } finally {
            Trace.traceEnd(TRACE_TAG_PACKAGE_MANAGER);
        }
    }
    private boolean performDexOptInternal(String packageName, String instructionSet,
                boolean useProfiles, boolean extractOnly) {
                boolean useProfiles, boolean extractOnly, boolean force) {
        PackageParser.Package p;
        final String targetInstructionSet;
        synchronized (mPackages) {
@@ -6701,7 +6703,7 @@ public class PackageManagerService extends IPackageManager.Stub {
            targetInstructionSet = instructionSet != null ? instructionSet :
                    getPrimaryInstructionSet(p.applicationInfo);
            if (!useProfiles && p.mDexOptPerformed.contains(targetInstructionSet)) {
            if (!force && !useProfiles && p.mDexOptPerformed.contains(targetInstructionSet)) {
                // Skip only if we do not use profiles since they might trigger a recompilation.
                return false;
            }
@@ -6711,7 +6713,7 @@ public class PackageManagerService extends IPackageManager.Stub {
            synchronized (mInstallLock) {
                final String[] instructionSets = new String[] { targetInstructionSet };
                int result = mPackageDexOptimizer.performDexOpt(p, instructionSets,
                        true /* inclDependencies */, useProfiles, extractOnly);
                        true /* inclDependencies */, useProfiles, extractOnly, force);
                return result == PackageDexOptimizer.DEX_OPT_PERFORMED;
            }
        } finally {
@@ -6757,7 +6759,7 @@ public class PackageManagerService extends IPackageManager.Stub {
            // Don't use profiles since that may cause compilation to be skipped.
            final int res = mPackageDexOptimizer.performDexOpt(pkg, instructionSets,
                    true /* inclDependencies */, false /* useProfiles */,
                    false /* extractOnly */);
                    false /* extractOnly */, true /* force */);
            Trace.traceEnd(TRACE_TAG_PACKAGE_MANAGER);
            if (res != PackageDexOptimizer.DEX_OPT_PERFORMED) {
@@ -13025,7 +13027,7 @@ public class PackageManagerService extends IPackageManager.Stub {
                // method because `pkg` is not in `mPackages` yet.
                int result = mPackageDexOptimizer.performDexOpt(pkg, null /* instructionSets */,
                        false /* inclDependencies */, false /* useProfiles */,
                        true /* extractOnly */);
                        true /* extractOnly */, false /* force */);
                Trace.traceEnd(TRACE_TAG_PACKAGE_MANAGER);
                if (result == PackageDexOptimizer.DEX_OPT_FAILED) {
                    String msg = "Extracking package failed for " + pkgName;
+70 −0
Original line number Diff line number Diff line
@@ -44,6 +44,7 @@ import android.os.Build;
import android.os.Bundle;
import android.os.RemoteException;
import android.os.ShellCommand;
import android.os.SystemProperties;
import android.os.UserHandle;
import android.text.TextUtils;
import android.util.PrintWriterPrinter;
@@ -96,6 +97,8 @@ class PackageManagerShellCommand extends ShellCommand {
                    return runInstallCreate();
                case "install-write":
                    return runInstallWrite();
                case "compile":
                    return runCompile();
                case "list":
                    return runList();
                case "uninstall":
@@ -227,6 +230,67 @@ class PackageManagerShellCommand extends ShellCommand {
        return doWriteSession(sessionId, path, sizeBytes, splitName, true /*logSuccess*/);
    }

    private int runCompile() throws RemoteException {
        final PrintWriter pw = getOutPrintWriter();
        boolean useJitProfiles = false;
        boolean extractOnly = false;
        boolean forceCompilation = false;
        String compilationMode = "default";

        String opt;
        while ((opt = getNextOption()) != null) {
            switch (opt) {
                case "-m":
                    compilationMode = getNextArgRequired();
                    break;
                case "-f":
                    forceCompilation = true;
                    break;
                default:
                    pw.println("Error: Unknown option: " + opt);
                    return 1;
            }
        }

        switch (compilationMode) {
            case "default":
                useJitProfiles = SystemProperties.getBoolean("dalvik.vm.usejitprofiles", false);
                extractOnly = false;
                break;
            case "all":
                useJitProfiles = false;
                extractOnly = false;
                break;
            case "profile":
                useJitProfiles = true;
                extractOnly = false;
                break;
            case "extract":
                useJitProfiles = false;
                extractOnly = true;
                break;
            default:
                pw.println("Error: Unknown compilation mode: " + compilationMode);
                return 1;
        }

        String packageName = getNextArg();
        if (packageName == null) {
            pw.println("Error: package name not specified");
            return 1;
        }

        boolean success = mInterface.performDexOpt(packageName, null /* instructionSet */,
                useJitProfiles, extractOnly, forceCompilation);
        if (success) {
            pw.println("Success");
            return 0;
        } else {
            pw.println("Failure: package " + packageName + " could not be compiled");
            return 1;
        }
    }

    private int runList() throws RemoteException {
        final PrintWriter pw = getOutPrintWriter();
        final String type = getNextArg();
@@ -1069,6 +1133,12 @@ class PackageManagerShellCommand extends ShellCommand {
        pw.println("  help");
        pw.println("    Print this help text.");
        pw.println("");
        pw.println("  compile [-m MODE] [-f] TARGET-PACKAGE");
        pw.println("    Trigger compilation of TARGET-PACKAGE.");
        pw.println("    Options:");
        pw.println("      -m: select compilation mode");
        pw.println("          MODE can be one of \"default\", \"all\", \"profile\", and \"extract\"");
        pw.println("      -f: force compilation even if not needed");
        pw.println("  list features");
        pw.println("    Prints all features of the system.");
        pw.println("  list instrumentation [-f] [TARGET-PACKAGE]");