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

Commit c6494490 authored by Calin Juravle's avatar Calin Juravle
Browse files

Use DexManager logic to decide if a package is used by other apps

Stop relying on the file marker recorded by the runtime. We have the
same data available from the DexManager.

The clean up CL to remove the handling of the file markers will follow.

Test: verify that "shared packages" (e.g. gmscore) are not compiled with speed-profile.

Bug: 32871170

(cherry picked from commit 07b6eabe)

Change-Id: I2969b75fa77d38dde0073ef67aa89b1dc91237b5

Merged-In: I6cc5834ac88489e69896cd5fba9ed9968aa7f5a2
parent f8afcdc7
Loading
Loading
Loading
Loading
+2 −1
Original line number Diff line number Diff line
@@ -313,7 +313,8 @@ public class OtaDexoptService extends IOtaDexopt.Stub {
        optimizer.performDexOpt(pkg, libraryDependencies,
                null /* ISAs */, false /* checkProfiles */,
                getCompilerFilterForReason(compilationReason),
                null /* CompilerStats.PackageStats */);
                null /* CompilerStats.PackageStats */,
                mPackageManagerService.getDexManager().isUsedByOtherApps(pkg.packageName));

        return commands;
    }
+5 −38
Original line number Diff line number Diff line
@@ -104,7 +104,7 @@ public class PackageDexOptimizer {
     */
    int performDexOpt(PackageParser.Package pkg, String[] sharedLibraries,
            String[] instructionSets, boolean checkProfiles, String targetCompilationFilter,
            CompilerStats.PackageStats packageStats) {
            CompilerStats.PackageStats packageStats, boolean isUsedByOtherApps) {
        if (!canOptimizePackage(pkg)) {
            return DEX_OPT_SKIPPED;
        }
@@ -119,7 +119,7 @@ public class PackageDexOptimizer {
            }
            try {
                return performDexOptLI(pkg, sharedLibraries, instructionSets, checkProfiles,
                        targetCompilationFilter, packageStats);
                        targetCompilationFilter, packageStats, isUsedByOtherApps);
            } finally {
                if (useLock) {
                    mDexoptWakeLock.release();
@@ -135,7 +135,8 @@ public class PackageDexOptimizer {
    @GuardedBy("mInstallLock")
    private int performDexOptLI(PackageParser.Package pkg, String[] sharedLibraries,
            String[] targetInstructionSets, boolean checkForProfileUpdates,
            String targetCompilerFilter, CompilerStats.PackageStats packageStats) {
            String targetCompilerFilter, CompilerStats.PackageStats packageStats,
            boolean isUsedByOtherApps) {
        final String[] instructionSets = targetInstructionSets != null ?
                targetInstructionSets : getAppDexInstructionSets(pkg.applicationInfo);
        final String[] dexCodeInstructionSets = getDexCodeInstructionSets(instructionSets);
@@ -143,7 +144,7 @@ public class PackageDexOptimizer {
        final int sharedGid = UserHandle.getSharedAppGid(pkg.applicationInfo.uid);

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

@@ -477,40 +478,6 @@ public class PackageDexOptimizer {
        mSystemReady = true;
    }

    /**
     * Returns true if the profiling data collected for the given app indicate
     * that the apps's APK has been loaded by another app.
     * Note that this returns false for all forward-locked apps and apps without
     * any collected profiling data.
     */
    public static boolean isUsedByOtherApps(PackageParser.Package pkg) {
        if (pkg.isForwardLocked()) {
            // Skip the check for forward locked packages since they don't share their code.
            return false;
        }

        for (String apkPath : pkg.getAllCodePathsExcludingResourceOnly()) {
            try {
                apkPath = PackageManagerServiceUtils.realpath(new File(apkPath));
            } catch (IOException e) {
                // Log an error but continue without it.
                Slog.w(TAG, "Failed to get canonical path", e);
                continue;
            }
            String useMarker = apkPath.replace('/', '@');
            final int[] currentUserIds = UserManagerService.getInstance().getUserIds();
            for (int i = 0; i < currentUserIds.length; i++) {
                File profileDir =
                        Environment.getDataProfilesDeForeignDexDirectory(currentUserIds[i]);
                File foreignUseMark = new File(profileDir, useMarker);
                if (foreignUseMark.exists()) {
                    return true;
                }
            }
        }
        return false;
    }

    private String printDexoptFlags(int flags) {
        ArrayList<String> flagsList = new ArrayList<>();

+6 −3
Original line number Diff line number Diff line
@@ -7498,11 +7498,13 @@ public class PackageManagerService extends IPackageManager.Stub {
                pdo.performDexOpt(depPackage, null /* sharedLibraries */, instructionSets,
                        false /* checkProfiles */,
                        getCompilerFilterForReason(REASON_NON_SYSTEM_LIBRARY),
                        getOrCreateCompilerPackageStats(depPackage));
                        getOrCreateCompilerPackageStats(depPackage),
                        mDexManager.isUsedByOtherApps(p.packageName));
            }
        }
        return pdo.performDexOpt(p, p.usesLibraryFiles, instructionSets, checkProfiles,
                targetCompilerFilter, getOrCreateCompilerPackageStats(p));
                targetCompilerFilter, getOrCreateCompilerPackageStats(p),
                mDexManager.isUsedByOtherApps(p.packageName));
    }
    // Performs dexopt on the used secondary dex files belonging to the given package.
@@ -15321,7 +15323,8 @@ public class PackageManagerService extends IPackageManager.Stub {
            mPackageDexOptimizer.performDexOpt(pkg, pkg.usesLibraryFiles,
                    null /* instructionSets */, false /* checkProfiles */,
                    getCompilerFilterForReason(REASON_INSTALL),
                    getOrCreateCompilerPackageStats(pkg));
                    getOrCreateCompilerPackageStats(pkg),
                    mDexManager.isUsedByOtherApps(pkg.packageName));
            Trace.traceEnd(TRACE_TAG_PACKAGE_MANAGER);
            // Notify BackgroundDexOptService that the package has been changed.
+2 −1
Original line number Diff line number Diff line
@@ -133,7 +133,8 @@ public class PackageManagerServiceUtils {
                sortTemp, packageManagerService);

        // Give priority to apps used by other apps.
        applyPackageFilter((pkg) -> PackageDexOptimizer.isUsedByOtherApps(pkg), result,
        applyPackageFilter((pkg) ->
                packageManagerService.getDexManager().isUsedByOtherApps(pkg.packageName), result,
                remainingPkgs, sortTemp, packageManagerService);

        // Filter out packages that aren't recently used, add all remaining apps.
+17 −0
Original line number Diff line number Diff line
@@ -358,6 +358,23 @@ public class DexManager {
        return mPackageDexUsage.getAllPackagesWithSecondaryDexFiles();
    }

    /**
     * Return true if the profiling data collected for the given app indicate
     * that the apps's APK has been loaded by another app.
     * Note that this returns false for all apps without any collected profiling data.
    */
    public boolean isUsedByOtherApps(String packageName) {
        PackageUseInfo useInfo = getPackageUseInfo(packageName);
        if (useInfo == null) {
            // No use info, means the package was not used or it was used but not by other apps.
            // Note that right now we might prune packages which are not used by other apps.
            // TODO(calin): maybe we should not (prune) so we can have an accurate view when we try
            // to access the package use.
            return false;
        }
        return useInfo.isUsedByOtherApps();
    }

    /**
     * Retrieves the package which owns the given dexPath.
     */