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

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

Don't recompile apks with speed-profile is the profile is empty am: 7e7619c3...

Don't recompile apks with speed-profile is the profile is empty am: 7e7619c3 am: 26ece569 am: ef956d35

Original change: https://android-review.googlesource.com/c/platform/frameworks/base/+/1730952

Change-Id: Idef380633706e3315fe6d8d33c79ee328d49edf6
parents ee5718a8 ef956d35
Loading
Loading
Loading
Loading
+22 −2
Original line number Original line Diff line number Diff line
@@ -80,6 +80,17 @@ public class Installer extends SystemService {
    /** Indicates that dexopt may be run with different performance / priority tuned for restore */
    /** Indicates that dexopt may be run with different performance / priority tuned for restore */
    public static final int DEXOPT_FOR_RESTORE = 1 << 13; // TODO(b/135202722): remove
    public static final int DEXOPT_FOR_RESTORE = 1 << 13; // TODO(b/135202722): remove


    /** The result of the profile analysis indicating that the app should be optimized. */
    public static final int PROFILE_ANALYSIS_OPTIMIZE = 1;
    /** The result of the profile analysis indicating that the app should not be optimized. */
    public static final int PROFILE_ANALYSIS_DONT_OPTIMIZE_SMALL_DELTA = 2;
    /**
     * The result of the profile analysis indicating that the app should not be optimized because
     * the profiles are empty.
     */
    public static final int PROFILE_ANALYSIS_DONT_OPTIMIZE_EMPTY_PROFILES = 3;


    public static final int FLAG_STORAGE_DE = IInstalld.FLAG_STORAGE_DE;
    public static final int FLAG_STORAGE_DE = IInstalld.FLAG_STORAGE_DE;
    public static final int FLAG_STORAGE_CE = IInstalld.FLAG_STORAGE_CE;
    public static final int FLAG_STORAGE_CE = IInstalld.FLAG_STORAGE_CE;
    public static final int FLAG_STORAGE_EXTERNAL = IInstalld.FLAG_STORAGE_EXTERNAL;
    public static final int FLAG_STORAGE_EXTERNAL = IInstalld.FLAG_STORAGE_EXTERNAL;
@@ -496,9 +507,18 @@ public class Installer extends SystemService {
        }
        }
    }
    }


    public boolean mergeProfiles(int uid, String packageName, String profileName)
    /**
     * Analyzes the ART profiles of the given package, possibly merging the information
     * into the reference profile. Returns whether or not we should optimize the package
     * based on how much information is in the profile.
     *
     * @return one of {@link #PROFILE_ANALYSIS_OPTIMIZE},
     *         {@link #PROFILE_ANALYSIS_DONT_OPTIMIZE_SMALL_DELTA},
     *         {@link #PROFILE_ANALYSIS_DONT_OPTIMIZE_EMPTY_PROFILES}
     */
    public int mergeProfiles(int uid, String packageName, String profileName)
            throws InstallerException {
            throws InstallerException {
        if (!checkBeforeRemote()) return false;
        if (!checkBeforeRemote()) return PROFILE_ANALYSIS_DONT_OPTIMIZE_SMALL_DELTA;
        try {
        try {
            return mInstalld.mergeProfiles(uid, packageName, profileName);
            return mInstalld.mergeProfiles(uid, packageName, profileName);
        } catch (Exception e) {
        } catch (Exception e) {
+41 −13
Original line number Original line Diff line number Diff line
@@ -31,6 +31,9 @@ import static com.android.server.pm.Installer.DEXOPT_PUBLIC;
import static com.android.server.pm.Installer.DEXOPT_SECONDARY_DEX;
import static com.android.server.pm.Installer.DEXOPT_SECONDARY_DEX;
import static com.android.server.pm.Installer.DEXOPT_STORAGE_CE;
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.Installer.DEXOPT_STORAGE_DE;
import static com.android.server.pm.Installer.PROFILE_ANALYSIS_DONT_OPTIMIZE_EMPTY_PROFILES;
import static com.android.server.pm.Installer.PROFILE_ANALYSIS_DONT_OPTIMIZE_SMALL_DELTA;
import static com.android.server.pm.Installer.PROFILE_ANALYSIS_OPTIMIZE;
import static com.android.server.pm.InstructionSets.getAppDexInstructionSets;
import static com.android.server.pm.InstructionSets.getAppDexInstructionSets;
import static com.android.server.pm.InstructionSets.getDexCodeInstructionSets;
import static com.android.server.pm.InstructionSets.getDexCodeInstructionSets;
import static com.android.server.pm.PackageManagerService.PLATFORM_PACKAGE_NAME;
import static com.android.server.pm.PackageManagerService.PLATFORM_PACKAGE_NAME;
@@ -248,8 +251,12 @@ public class PackageDexOptimizer {
                    || packageUseInfo.isUsedByOtherApps(path);
                    || packageUseInfo.isUsedByOtherApps(path);
            final String compilerFilter = getRealCompilerFilter(pkg,
            final String compilerFilter = getRealCompilerFilter(pkg,
                options.getCompilerFilter(), isUsedByOtherApps);
                options.getCompilerFilter(), isUsedByOtherApps);
            final boolean profileUpdated = options.isCheckForProfileUpdates() &&
            // If we don't have to check for profiles updates assume
                isProfileUpdated(pkg, sharedGid, profileName, compilerFilter);
            // PROFILE_ANALYSIS_DONT_OPTIMIZE_SMALL_DELTA which will be a no-op with respect to
            // profiles.
            final int profileAnalysisResult = options.isCheckForProfileUpdates()
                    ? analyseProfiles(pkg, sharedGid, profileName, compilerFilter)
                    : PROFILE_ANALYSIS_DONT_OPTIMIZE_SMALL_DELTA;


            // Get the dexopt flags after getRealCompilerFilter to make sure we get the correct
            // Get the dexopt flags after getRealCompilerFilter to make sure we get the correct
            // flags.
            // flags.
@@ -257,7 +264,7 @@ public class PackageDexOptimizer {


            for (String dexCodeIsa : dexCodeInstructionSets) {
            for (String dexCodeIsa : dexCodeInstructionSets) {
                int newResult = dexOptPath(pkg, pkgSetting, path, dexCodeIsa, compilerFilter,
                int newResult = dexOptPath(pkg, pkgSetting, path, dexCodeIsa, compilerFilter,
                        profileUpdated, classLoaderContexts[i], dexoptFlags, sharedGid,
                        profileAnalysisResult, classLoaderContexts[i], dexoptFlags, sharedGid,
                        packageStats, options.isDowngrade(), profileName, dexMetadataPath,
                        packageStats, options.isDowngrade(), profileName, dexMetadataPath,
                        options.getCompilationReason());
                        options.getCompilationReason());


@@ -306,11 +313,11 @@ public class PackageDexOptimizer {
     */
     */
    @GuardedBy("mInstallLock")
    @GuardedBy("mInstallLock")
    private int dexOptPath(AndroidPackage pkg, @NonNull PackageSetting pkgSetting, String path,
    private int dexOptPath(AndroidPackage pkg, @NonNull PackageSetting pkgSetting, String path,
            String isa, String compilerFilter, boolean profileUpdated, String classLoaderContext,
            String isa, String compilerFilter, int profileAnalysisResult, String classLoaderContext,
            int dexoptFlags, int uid, CompilerStats.PackageStats packageStats, boolean downgrade,
            int dexoptFlags, int uid, CompilerStats.PackageStats packageStats, boolean downgrade,
            String profileName, String dexMetadataPath, int compilationReason) {
            String profileName, String dexMetadataPath, int compilationReason) {
        int dexoptNeeded = getDexoptNeeded(path, isa, compilerFilter, classLoaderContext,
        int dexoptNeeded = getDexoptNeeded(path, isa, compilerFilter, classLoaderContext,
                profileUpdated, downgrade);
                profileAnalysisResult, downgrade);
        if (Math.abs(dexoptNeeded) == DexFile.NO_DEXOPT_NEEDED) {
        if (Math.abs(dexoptNeeded) == DexFile.NO_DEXOPT_NEEDED) {
            return DEX_OPT_SKIPPED;
            return DEX_OPT_SKIPPED;
        }
        }
@@ -364,7 +371,7 @@ public class PackageDexOptimizer {
                    isa,
                    isa,
                    options.getCompilerFilter(),
                    options.getCompilerFilter(),
                    dexUseInfo.getClassLoaderContext(),
                    dexUseInfo.getClassLoaderContext(),
                    /* newProfile= */false,
                    PROFILE_ANALYSIS_DONT_OPTIMIZE_EMPTY_PROFILES,
                    /* downgrade= */ false);
                    /* downgrade= */ false);


            if (dexoptNeeded == DexFile.NO_DEXOPT_NEEDED) {
            if (dexoptNeeded == DexFile.NO_DEXOPT_NEEDED) {
@@ -750,11 +757,25 @@ public class PackageDexOptimizer {
     * configuration (isa, compiler filter, profile).
     * configuration (isa, compiler filter, profile).
     */
     */
    private int getDexoptNeeded(String path, String isa, String compilerFilter,
    private int getDexoptNeeded(String path, String isa, String compilerFilter,
            String classLoaderContext, boolean newProfile, boolean downgrade) {
            String classLoaderContext, int profileAnalysisResult, boolean downgrade) {
        int dexoptNeeded;
        int dexoptNeeded;
        try {
        try {
            dexoptNeeded = DexFile.getDexOptNeeded(path, isa, compilerFilter, classLoaderContext,
            // A profile guided optimizations with an empty profile is essentially 'verify' and
                    newProfile, downgrade);
            // dex2oat already makes this transformation. However DexFile.getDexOptNeeded() cannot
            // check the profiles because system server does not have access to them.
            // As such, we rely on the previous profile analysis (done with dexoptanalyzer) and
            // manually adjust the actual filter before checking.
            //
            // TODO: ideally. we'd move this check in dexoptanalyzer, but that's a large change,
            // and in the interim we can still improve things here.
            String actualCompilerFilter = compilerFilter;
            if (compilerFilterDependsOnProfiles(compilerFilter)
                    && profileAnalysisResult == PROFILE_ANALYSIS_DONT_OPTIMIZE_EMPTY_PROFILES) {
                actualCompilerFilter = "verify";
            }
            boolean newProfile = profileAnalysisResult == PROFILE_ANALYSIS_OPTIMIZE;
            dexoptNeeded = DexFile.getDexOptNeeded(path, isa, actualCompilerFilter,
                    classLoaderContext, newProfile, downgrade);
        } catch (IOException ioe) {
        } catch (IOException ioe) {
            Slog.w(TAG, "IOException reading apk: " + path, ioe);
            Slog.w(TAG, "IOException reading apk: " + path, ioe);
            return DEX_OPT_FAILED;
            return DEX_OPT_FAILED;
@@ -765,27 +786,34 @@ public class PackageDexOptimizer {
        return adjustDexoptNeeded(dexoptNeeded);
        return adjustDexoptNeeded(dexoptNeeded);
    }
    }


    /** Returns true if the compiler filter depends on profiles (e.g speed-profile). */
    private boolean compilerFilterDependsOnProfiles(String compilerFilter) {
        return compilerFilter.endsWith("-profile");
    }

    /**
    /**
     * Checks if there is an update on the profile information of the {@code pkg}.
     * Checks if there is an update on the profile information of the {@code pkg}.
     * If the compiler filter is not profile guided the method returns false.
     * If the compiler filter is not profile guided the method returns a safe default:
     * PROFILE_ANALYSIS_DONT_OPTIMIZE_SMALL_DELTA.
     *
     *
     * Note that this is a "destructive" operation with side effects. Under the hood the
     * Note that this is a "destructive" operation with side effects. Under the hood the
     * current profile and the reference profile will be merged and subsequent calls
     * current profile and the reference profile will be merged and subsequent calls
     * may return a different result.
     * may return a different result.
     */
     */
    private boolean isProfileUpdated(AndroidPackage pkg, int uid, String profileName,
    private int analyseProfiles(AndroidPackage pkg, int uid, String profileName,
            String compilerFilter) {
            String compilerFilter) {
        // Check if we are allowed to merge and if the compiler filter is profile guided.
        // Check if we are allowed to merge and if the compiler filter is profile guided.
        if (!isProfileGuidedCompilerFilter(compilerFilter)) {
        if (!isProfileGuidedCompilerFilter(compilerFilter)) {
            return false;
            return PROFILE_ANALYSIS_DONT_OPTIMIZE_SMALL_DELTA;
        }
        }
        // Merge profiles. It returns whether or not there was an updated in the profile info.
        // Merge profiles. It returns whether or not there was an updated in the profile info.
        try {
        try {
            return mInstaller.mergeProfiles(uid, pkg.getPackageName(), profileName);
            return mInstaller.mergeProfiles(uid, pkg.getPackageName(), profileName);
        } catch (InstallerException e) {
        } catch (InstallerException e) {
            Slog.w(TAG, "Failed to merge profiles", e);
            Slog.w(TAG, "Failed to merge profiles", e);
            // We don't need to optimize if we failed to merge.
            return PROFILE_ANALYSIS_DONT_OPTIMIZE_SMALL_DELTA;
        }
        }
        return false;
    }
    }


    /**
    /**