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

Commit e319c4db authored by Calin Juravle's avatar Calin Juravle Committed by Automerger Merge Worker
Browse files

Merge "Enable dexopt for system server dex files" into rvc-dev am: fe928477 am: bd96b9b8

Change-Id: I36ec5afd2cf72db081b145527f301563960f7f04
parents 1a11f302 bd96b9b8
Loading
Loading
Loading
Loading
+51 −1
Original line number Diff line number Diff line
@@ -51,6 +51,7 @@ import android.os.SystemClock;
import android.os.SystemProperties;
import android.os.UserHandle;
import android.os.WorkSource;
import android.os.storage.StorageManager;
import android.util.Log;
import android.util.Slog;
import android.util.SparseArray;
@@ -79,7 +80,7 @@ import java.util.Map;
 * Helper class for running dexopt command on packages.
 */
public class PackageDexOptimizer {
    private static final String TAG = "PackageManager.DexOptimizer";
    private static final String TAG = "PackageDexOptimizer";
    static final String OAT_DIR_NAME = "oat";
    // TODO b/19550105 Remove error codes and use exceptions
    public static final int DEX_OPT_SKIPPED = 0;
@@ -307,6 +308,55 @@ public class PackageDexOptimizer {
        }
    }

    /**
     * Perform dexopt (if needed) on a system server code path).
     */
    public int dexoptSystemServerPath(
            String dexPath, PackageDexUsage.DexUseInfo dexUseInfo, DexoptOptions options) {
        int dexoptFlags = DEXOPT_PUBLIC
                | (options.isBootComplete() ? DEXOPT_BOOTCOMPLETE : 0)
                | (options.isDexoptIdleBackgroundJob() ? DEXOPT_IDLE_BACKGROUND_JOB : 0);

        int result = DEX_OPT_SKIPPED;
        for (String isa : dexUseInfo.getLoaderIsas()) {
            int dexoptNeeded = getDexoptNeeded(
                    dexPath,
                    isa,
                    options.getCompilerFilter(),
                    dexUseInfo.getClassLoaderContext(),
                    /* newProfile= */false,
                    /* downgrade= */ false);

            if (dexoptNeeded == DexFile.NO_DEXOPT_NEEDED) {
                continue;
            }
            try {
                mInstaller.dexopt(
                        dexPath,
                        android.os.Process.SYSTEM_UID,
                        /* packageName= */ "android",
                        isa,
                        dexoptNeeded,
                        /* oatDir= */ null,
                        dexoptFlags,
                        options.getCompilerFilter(),
                        StorageManager.UUID_PRIVATE_INTERNAL,
                        dexUseInfo.getClassLoaderContext(),
                        /* seInfo= */ null,
                        /* downgrade= */ false ,
                        /* targetSdk= */ 0,
                        /* profileName */ null,
                        /* dexMetadataPath */ null,
                        getReasonName(options.getCompilationReason()));
            } catch (InstallerException e) {
                Slog.w(TAG, "Failed to dexopt", e);
                return DEX_OPT_FAILED;
            }
            result = DEX_OPT_PERFORMED;
        }
        return result;
    }

    private String getAugmentedReasonName(int compilationReason, boolean useDexMetadata) {
        String annotation = useDexMetadata
                ? ArtManagerService.DEXOPT_REASON_WITH_DEX_METADATA_ANNOTATION : "";
+5 −0
Original line number Diff line number Diff line
@@ -9855,6 +9855,11 @@ public class PackageManagerService extends IPackageManager.Stub
    private int performDexOptInternalWithDependenciesLI(AndroidPackage p,
            @NonNull PackageSetting pkgSetting, DexoptOptions options) {
        // System server gets a special path.
        if (PLATFORM_PACKAGE_NAME.equals(p.getPackageName())) {
            return mDexManager.dexoptSystemServer(options);
        }
        // Select the dex optimizer based on the force parameter.
        // Note: The force option is rarely used (cmdline input for testing, mostly), so it's OK to
        //       allocate an object here.
+80 −9
Original line number Diff line number Diff line
@@ -49,6 +49,8 @@ import dalvik.system.VMRuntime;

import java.io.File;
import java.io.IOException;
import java.nio.file.Files;
import java.nio.file.Paths;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Collection;
@@ -437,15 +439,7 @@ public class DexManager {
     *         because they don't need to be compiled)..
     */
    public boolean dexoptSecondaryDex(DexoptOptions options) {
        // Select the dex optimizer based on the force parameter.
        // Forced compilation is done through ForcedUpdatePackageDexOptimizer which will adjust
        // the necessary dexopt flags to make sure that compilation is not skipped. This avoid
        // passing the force flag through the multitude of layers.
        // Note: The force option is rarely used (cmdline input for testing, mostly), so it's OK to
        //       allocate an object here.
        PackageDexOptimizer pdo = options.isForce()
                ? new PackageDexOptimizer.ForcedUpdatePackageDexOptimizer(mPackageDexOptimizer)
                : mPackageDexOptimizer;
        PackageDexOptimizer pdo = getPackageDexOptimizer(options);
        String packageName = options.getPackageName();
        PackageUseInfo useInfo = getPackageUseInfoOrDefault(packageName);
        if (useInfo.getDexUseInfoMap().isEmpty()) {
@@ -485,6 +479,83 @@ public class DexManager {
        return success;
    }

    /**
     * Performs dexopt on system server dex files.
     *
     * <p>Verfifies that the package name is {@link PackageManagerService#PLATFORM_PACKAGE_NAME}.
     *
     * @return
     * <p>PackageDexOptimizer.DEX_OPT_SKIPPED if dexopt was skipped because no system server
     * files were recorded or if no dexopt was needed.
     * <p>PackageDexOptimizer.DEX_OPT_FAILED if any dexopt operation failed.
     * <p>PackageDexOptimizer.DEX_OPT_PERFORMED if all dexopt operations succeeded.
     */
    public int dexoptSystemServer(DexoptOptions options) {
        if (!PLATFORM_PACKAGE_NAME.equals(options.getPackageName())) {
            Slog.wtf(TAG, "Non system server package used when trying to dexopt system server:"
                    + options.getPackageName());
            return PackageDexOptimizer.DEX_OPT_FAILED;
        }

        PackageDexOptimizer pdo = getPackageDexOptimizer(options);
        String packageName = options.getPackageName();
        PackageUseInfo useInfo = getPackageUseInfoOrDefault(packageName);
        if (useInfo.getDexUseInfoMap().isEmpty()) {
            if (DEBUG) {
                Slog.d(TAG, "No dex files recorded for system server");
            }
            // Nothing to compile, return true.
            return PackageDexOptimizer.DEX_OPT_SKIPPED;
        }

        boolean usageUpdated = false;
        int result = PackageDexOptimizer.DEX_OPT_SKIPPED;
        for (Map.Entry<String, DexUseInfo> entry : useInfo.getDexUseInfoMap().entrySet()) {
            String dexPath = entry.getKey();
            DexUseInfo dexUseInfo = entry.getValue();
            if (!Files.exists(Paths.get(dexPath))) {
                if (DEBUG) {
                    Slog.w(TAG, "A dex file previously loaded by System Server does not exist "
                            + " anymore: " + dexPath);
                }
                usageUpdated = mPackageDexUsage.removeDexFile(
                            packageName, dexPath, dexUseInfo.getOwnerUserId()) || usageUpdated;
                continue;
            }

            int newResult = pdo.dexoptSystemServerPath(dexPath, dexUseInfo, options);

            // The end result is:
            //  - FAILED if any path failed,
            //  - PERFORMED if at least one path needed compilation,
            //  - SKIPPED when all paths are up to date
            if ((result != PackageDexOptimizer.DEX_OPT_FAILED)
                    && (newResult != PackageDexOptimizer.DEX_OPT_SKIPPED)) {
                result = newResult;
            }
        }

        if (usageUpdated) {
            mPackageDexUsage.maybeWriteAsync();
        }

        return result;
    }

    /**
     * Select the dex optimizer based on the force parameter.
     * Forced compilation is done through ForcedUpdatePackageDexOptimizer which will adjust
     * the necessary dexopt flags to make sure that compilation is not skipped. This avoid
     * passing the force flag through the multitude of layers.
     * Note: The force option is rarely used (cmdline input for testing, mostly), so it's OK to
     *       allocate an object here.
     */
    private PackageDexOptimizer getPackageDexOptimizer(DexoptOptions options) {
        return options.isForce()
                ? new PackageDexOptimizer.ForcedUpdatePackageDexOptimizer(mPackageDexOptimizer)
                : mPackageDexOptimizer;
    }

    /**
     * Reconcile the information we have about the secondary dex files belonging to
     * {@code packagName} and the actual dex files. For all dex files that were