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

Commit 468be64c authored by Calin Juravle's avatar Calin Juravle Committed by android-build-merger
Browse files

Compile secondary dex files in DexManager

am: 7218363a

Change-Id: I53e7864b097cf9cff702e9185bb1c9091d97fe63
parents 27ea5920 7218363a
Loading
Loading
Loading
Loading
+11 −0
Original line number Diff line number Diff line
@@ -482,6 +482,7 @@ interface IPackageManager {
     */
    boolean performDexOpt(String packageName, boolean checkProfiles,
            int compileReason, boolean force);

    /**
     * Ask the package manager to perform a dex-opt with the given compiler filter.
     *
@@ -491,6 +492,16 @@ interface IPackageManager {
    boolean performDexOptMode(String packageName, boolean checkProfiles,
            String targetCompilerFilter, boolean force);

    /**
     * Ask the package manager to perform a dex-opt with the given compiler filter on the
     * secondary dex files belonging to the given package.
     *
     * Note: exposed only for the shell command to allow moving packages explicitly to a
     *       definite state.
     */
    boolean performDexOptSecondary(String packageName,
            String targetCompilerFilter, boolean force);

    /**
     * Ask the package manager to dump profiles associated with a package.
     */
+8 −0
Original line number Diff line number Diff line
@@ -50,6 +50,14 @@ public class Installer extends SystemService {
    public static final int DEXOPT_BOOTCOMPLETE   = 1 << 4;
    /** Hint that the dexopt type is profile-guided. */
    public static final int DEXOPT_PROFILE_GUIDED = 1 << 5;
    /** The compilation is for a secondary dex file. */
    public static final int DEXOPT_SECONDARY_DEX  = 1 << 6;
    /** Ignore the result of dexoptNeeded and force compilation. */
    public static final int DEXOPT_FORCE          = 1 << 7;
    /** Indicates that the dex file passed to dexopt in on CE storage. */
    public static final int DEXOPT_STORAGE_CE     = 1 << 8;
    /** Indicates that the dex file passed to dexopt in on DE storage. */
    public static final int DEXOPT_STORAGE_DE     = 1 << 9;

    // NOTE: keep in sync with installd
    public static final int FLAG_CLEAR_CACHE_ONLY = 1 << 8;
+119 −10
Original line number Diff line number Diff line
@@ -19,6 +19,7 @@ package com.android.server.pm;
import android.annotation.Nullable;
import android.content.Context;
import android.content.pm.ApplicationInfo;
import android.content.pm.PackageInfo;
import android.content.pm.PackageParser;
import android.os.Environment;
import android.os.PowerManager;
@@ -35,6 +36,7 @@ import java.io.File;
import java.io.IOException;
import java.util.ArrayList;
import java.util.List;
import java.util.Set;

import dalvik.system.DexFile;

@@ -43,6 +45,10 @@ import static com.android.server.pm.Installer.DEXOPT_DEBUGGABLE;
import static com.android.server.pm.Installer.DEXOPT_PROFILE_GUIDED;
import static com.android.server.pm.Installer.DEXOPT_PUBLIC;
import static com.android.server.pm.Installer.DEXOPT_SAFEMODE;
import static com.android.server.pm.Installer.DEXOPT_SECONDARY_DEX;
import static com.android.server.pm.Installer.DEXOPT_FORCE;
import static com.android.server.pm.Installer.DEXOPT_STORAGE_CE;
import static com.android.server.pm.Installer.DEXOPT_STORAGE_DE;
import static com.android.server.pm.InstructionSets.getAppDexInstructionSets;
import static com.android.server.pm.InstructionSets.getDexCodeInstructionSets;

@@ -52,13 +58,13 @@ import static dalvik.system.DexFile.isProfileGuidedCompilerFilter;
/**
 * Helper class for running dexopt command on packages.
 */
class PackageDexOptimizer {
public class PackageDexOptimizer {
    private static final String TAG = "PackageManager.DexOptimizer";
    static final String OAT_DIR_NAME = "oat";
    // TODO b/19550105 Remove error codes and use exceptions
    static final int DEX_OPT_SKIPPED = 0;
    static final int DEX_OPT_PERFORMED = 1;
    static final int DEX_OPT_FAILED = -1;
    public static final int DEX_OPT_SKIPPED = 0;
    public static final int DEX_OPT_PERFORMED = 1;
    public static final int DEX_OPT_FAILED = -1;

    private final Installer mInstaller;
    private final Object mInstallLock;
@@ -100,6 +106,9 @@ class PackageDexOptimizer {
            return DEX_OPT_SKIPPED;
        }
        synchronized (mInstallLock) {
            // During boot the system doesn't need to instantiate and obtain a wake lock.
            // PowerManager might not be ready, but that doesn't mean that we can't proceed with
            // dexopt.
            final boolean useLock = mSystemReady;
            if (useLock) {
                mDexoptWakeLock.setWorkSource(new WorkSource(pkg.applicationInfo.uid));
@@ -130,9 +139,11 @@ class PackageDexOptimizer {
        final List<String> paths = pkg.getAllCodePathsExcludingResourceOnly();
        final int sharedGid = UserHandle.getSharedAppGid(pkg.applicationInfo.uid);

        final String compilerFilter = getRealCompilerFilter(pkg, targetCompilerFilter);
        final String compilerFilter = getRealCompilerFilter(pkg.applicationInfo,
                targetCompilerFilter, isUsedByOtherApps(pkg));
        final boolean profileUpdated = checkForProfileUpdates &&
                isProfileUpdated(pkg, sharedGid, compilerFilter);

        // TODO(calin,jeffhao): shared library paths should be adjusted to include previous code
        // paths (b/34169257).
        final String sharedLibrariesPath = getSharedLibrariesPath(sharedLibraries);
@@ -200,6 +211,79 @@ class PackageDexOptimizer {
        }
    }

    /**
     * Performs dexopt on the secondary dex {@code path} belonging to the app {@code info}.
     *
     * @return
     *      DEX_OPT_FAILED if there was any exception during dexopt
     *      DEX_OPT_PERFORMED if dexopt was performed successfully on the given path.
     * NOTE that DEX_OPT_PERFORMED for secondary dex files includes the case when the dex file
     * didn't need an update. That's because at the moment we don't get more than success/failure
     * from installd.
     *
     * TODO(calin): Consider adding return codes to installd dexopt invocation (rather than
     * throwing exceptions). Or maybe make a separate call to installd to get DexOptNeeded, though
     * that seems wasteful.
     */
    public int dexOptSecondaryDexPath(ApplicationInfo info, String path, Set<String> isas,
            String compilerFilter, boolean isUsedByOtherApps) {
        synchronized (mInstallLock) {
            // During boot the system doesn't need to instantiate and obtain a wake lock.
            // PowerManager might not be ready, but that doesn't mean that we can't proceed with
            // dexopt.
            final boolean useLock = mSystemReady;
            if (useLock) {
                mDexoptWakeLock.setWorkSource(new WorkSource(info.uid));
                mDexoptWakeLock.acquire();
            }
            try {
                return dexOptSecondaryDexPathLI(info, path, isas, compilerFilter,
                        isUsedByOtherApps);
            } finally {
                if (useLock) {
                    mDexoptWakeLock.release();
                }
            }
        }
    }

    @GuardedBy("mInstallLock")
    private int dexOptSecondaryDexPathLI(ApplicationInfo info, String path, Set<String> isas,
            String compilerFilter, boolean isUsedByOtherApps) {
        int dexoptFlags = getDexFlags(info, compilerFilter) | DEXOPT_SECONDARY_DEX;
        // Check the app storage and add the appropriate flags.
        if (info.dataDir.equals(info.deviceProtectedDataDir)) {
            dexoptFlags |= DEXOPT_STORAGE_DE;
        } else if (info.dataDir.equals(info.credentialProtectedDataDir)) {
            dexoptFlags |= DEXOPT_STORAGE_CE;
        } else {
            Slog.e(TAG, "Could not infer CE/DE storage for package " + info.packageName);
            return DEX_OPT_FAILED;
        }
        compilerFilter = getRealCompilerFilter(info, compilerFilter, isUsedByOtherApps);
        Log.d(TAG, "Running dexopt on: " + path
                + " pkg=" + info.packageName + " isa=" + isas
                + " dexoptFlags=" + printDexoptFlags(dexoptFlags)
                + " target-filter=" + compilerFilter);

        try {
            for (String isa : isas) {
                // Reuse the same dexopt path as for the primary apks. We don't need all the
                // arguments as some (dexopNeeded and oatDir) will be computed by installd because
                // system server cannot read untrusted app content.
                // TODO(calin): maybe add a separate call.
                mInstaller.dexopt(path, info.uid, info.packageName, isa, /*dexoptNeeded*/ 0,
                        /*oatDir*/ null, dexoptFlags,
                        compilerFilter, info.volumeUuid, /*sharedLibrariesPath*/ null);
            }

            return DEX_OPT_PERFORMED;
        } catch (InstallerException e) {
            Slog.w(TAG, "Failed to dexopt", e);
            return DEX_OPT_FAILED;
        }
    }

    /**
     * Adjust the given dexopt-needed value. Can be overridden to influence the decision to
     * optimize or not (and in what way).
@@ -246,8 +330,9 @@ class PackageDexOptimizer {
     * The target filter will be updated if the package code is used by other apps
     * or if it has the safe mode flag set.
     */
    private String getRealCompilerFilter(PackageParser.Package pkg, String targetCompilerFilter) {
        int flags = pkg.applicationInfo.flags;
    private String getRealCompilerFilter(ApplicationInfo info, String targetCompilerFilter,
            boolean isUsedByOtherApps) {
        int flags = info.flags;
        boolean vmSafeMode = (flags & ApplicationInfo.FLAG_VM_SAFE_MODE) != 0;
        if (vmSafeMode) {
            // For the compilation, it doesn't really matter what we return here because installd
@@ -259,7 +344,7 @@ class PackageDexOptimizer {
            return getNonProfileGuidedCompilerFilter(targetCompilerFilter);
        }

        if (isProfileGuidedCompilerFilter(targetCompilerFilter) && isUsedByOtherApps(pkg)) {
        if (isProfileGuidedCompilerFilter(targetCompilerFilter) && isUsedByOtherApps) {
            // If the dex files is used by other apps, we cannot use profile-guided compilation.
            return getNonProfileGuidedCompilerFilter(targetCompilerFilter);
        }
@@ -272,12 +357,16 @@ class PackageDexOptimizer {
     * filter.
     */
    private int getDexFlags(PackageParser.Package pkg, String compilerFilter) {
        int flags = pkg.applicationInfo.flags;
        return getDexFlags(pkg.applicationInfo, compilerFilter);
    }

    private int getDexFlags(ApplicationInfo info, String compilerFilter) {
        int flags = info.flags;
        boolean vmSafeMode = (flags & ApplicationInfo.FLAG_VM_SAFE_MODE) != 0;
        boolean debuggable = (flags & ApplicationInfo.FLAG_DEBUGGABLE) != 0;
        // Profile guide compiled oat files should not be public.
        boolean isProfileGuidedFilter = isProfileGuidedCompilerFilter(compilerFilter);
        boolean isPublic = !pkg.isForwardLocked() && !isProfileGuidedFilter;
        boolean isPublic = !info.isForwardLocked() && !isProfileGuidedFilter;
        int profileFlag = isProfileGuidedFilter ? DEXOPT_PROFILE_GUIDED : 0;
        int dexFlags =
                (isPublic ? DEXOPT_PUBLIC : 0)
@@ -437,6 +526,19 @@ class PackageDexOptimizer {
        if ((flags & DEXOPT_SAFEMODE) == DEXOPT_SAFEMODE) {
            flagsList.add("safemode");
        }
        if ((flags & DEXOPT_SECONDARY_DEX) == DEXOPT_SECONDARY_DEX) {
            flagsList.add("secondary");
        }
        if ((flags & DEXOPT_FORCE) == DEXOPT_FORCE) {
            flagsList.add("force");
        }
        if ((flags & DEXOPT_STORAGE_CE) == DEXOPT_STORAGE_CE) {
            flagsList.add("storage_ce");
        }
        if ((flags & DEXOPT_STORAGE_DE) == DEXOPT_STORAGE_DE) {
            flagsList.add("storage_de");
        }

        return String.join(",", flagsList);
    }

@@ -461,5 +563,12 @@ class PackageDexOptimizer {
            // TODO: The return value is wrong when patchoat is needed.
            return DexFile.DEX2OAT_FROM_SCRATCH;
        }

        @Override
        protected int adjustDexoptFlags(int flags) {
            // Add DEXOPT_FORCE flag to signal installd that it should force compilation
            // and discard dexoptanalyzer result.
            return flags | DEXOPT_FORCE;
        }
    }
}
+10 −1
Original line number Diff line number Diff line
@@ -2133,7 +2133,7 @@ public class PackageManagerService extends IPackageManager.Stub {
        mInstaller = installer;
        mPackageDexOptimizer = new PackageDexOptimizer(installer, mInstallLock, context,
                "*dexopt*");
        mDexManager = new DexManager();
        mDexManager = new DexManager(this, mPackageDexOptimizer);
        mMoveCallbacks = new MoveCallbacks(FgThread.get().getLooper());
        mOnPermissionChangeListeners = new OnPermissionChangeListeners(
@@ -7540,6 +7540,15 @@ public class PackageManagerService extends IPackageManager.Stub {
                targetCompilerFilter, getOrCreateCompilerPackageStats(p));
    }
    // Performs dexopt on the used secondary dex files belonging to the given package.
    // Returns true if all dex files were process successfully (which could mean either dexopt or
    // skip). Returns false if any of the files caused errors.
    @Override
    public boolean performDexOptSecondary(String packageName, String compilerFilter,
            boolean force) {
        return mDexManager.dexoptSecondaryDex(packageName, compilerFilter, force);
    }
    Collection<PackageParser.Package> findSharedNonSystemLibraries(PackageParser.Package p) {
        if (p.usesLibraries != null || p.usesOptionalLibraries != null) {
            ArrayList<PackageParser.Package> retValue = new ArrayList<>();
+1 −1
Original line number Diff line number Diff line
@@ -23,7 +23,7 @@ import dalvik.system.DexFile;
/**
 * Manage (retrieve) mappings from compilation reason to compilation filter.
 */
class PackageManagerServiceCompilerMapping {
public class PackageManagerServiceCompilerMapping {
    // Names for compilation reasons.
    static final String REASON_STRINGS[] = {
            "first-boot", "boot", "install", "bg-dexopt", "ab-ota", "nsys-library", "shared-apk",
Loading