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

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

Restrict the cases when we profile guided compile an apk

Do not use profile guided compilation if the apk is loaded by another
app. The decision if an apk was used or not by another app is done
by looking into the foreign profile directory. Apks which where
loaded in others apps will have a file marker in the profile directory.
The marker is  named after the canonical location of the apk file where
'/' is replaced by '@'.

Also, refactor the profile paths to the Environment.

Bug: 27334750
Bug: 26080105
Change-Id: Ic2ac5a7a231670ecb4462166c34fdd5b4c631178
parent e5bfd2da
Loading
Loading
Loading
Loading
+13 −3
Original line number Original line Diff line number Diff line
@@ -4776,8 +4776,9 @@ public final class ActivityThread {


    // Keep in sync with installd (frameworks/native/cmds/installd/commands.cpp).
    // Keep in sync with installd (frameworks/native/cmds/installd/commands.cpp).
    private static File getPrimaryProfileFile(String packageName) {
    private static File getPrimaryProfileFile(String packageName) {
         return new File("/data/misc/profiles/cur/" + UserHandle.myUserId() +
        File profileDir = Environment.getDataProfilesDePackageDirectory(
              "/" + packageName + "/primary.prof");
                UserHandle.myUserId(), packageName);
        return new File(profileDir, "primary.prof");
    }
    }


    private static void setupJitProfileSupport(LoadedApk loadedApk, File cacheDir) {
    private static void setupJitProfileSupport(LoadedApk loadedApk, File cacheDir) {
@@ -4820,8 +4821,17 @@ public final class ActivityThread {
            }
            }
        }
        }


        final File foreignDexProfilesFile =
                Environment.getDataProfilesDeForeignDexDirectory(UserHandle.myUserId());
        String foreignDexProfilesPath = null;
        if (!foreignDexProfilesFile.exists()) {
            Log.v(TAG, "ForeignDexProfilesPath does not exists:" +
                    foreignDexProfilesFile.getPath());
        } else {
            foreignDexProfilesPath = foreignDexProfilesFile.getAbsolutePath();
        }
        VMRuntime.registerAppInfo(profileFile.getAbsolutePath(), appInfo.dataDir,
        VMRuntime.registerAppInfo(profileFile.getAbsolutePath(), appInfo.dataDir,
                codePaths.toArray(new String[codePaths.size()]));
                codePaths.toArray(new String[codePaths.size()]), foreignDexProfilesPath);
    }
    }


    private void updateDefaultDensity() {
    private void updateDefaultDensity() {
+14 −0
Original line number Original line Diff line number Diff line
@@ -258,6 +258,20 @@ public class Environment {
        return buildPath(getDataDirectory(), "misc_de", String.valueOf(userId));
        return buildPath(getDataDirectory(), "misc_de", String.valueOf(userId));
    }
    }


    private static File getDataProfilesDeDirectory(int userId) {
        return buildPath(getDataDirectory(), "misc", "profiles", "cur", String.valueOf(userId));
    }

    /** {@hide} */
    public static File getDataProfilesDePackageDirectory(int userId, String packageName) {
        return buildPath(getDataProfilesDeDirectory(userId), packageName);
    }

    /** {@hide} */
    public static File getDataProfilesDeForeignDexDirectory(int userId) {
        return buildPath(getDataProfilesDeDirectory(userId), "foreign-dex");
    }

    /** {@hide} */
    /** {@hide} */
    public static File getDataAppDirectory(String volumeUuid) {
    public static File getDataAppDirectory(String volumeUuid) {
        return new File(getDataDirectory(volumeUuid), "app");
        return new File(getDataDirectory(volumeUuid), "app");
+27 −1
Original line number Original line Diff line number Diff line
@@ -21,6 +21,7 @@ import android.content.Context;
import android.content.pm.ApplicationInfo;
import android.content.pm.ApplicationInfo;
import android.content.pm.PackageParser;
import android.content.pm.PackageParser;
import android.content.pm.PackageParser.Package;
import android.content.pm.PackageParser.Package;
import android.os.Environment;
import android.os.PowerManager;
import android.os.PowerManager;
import android.os.UserHandle;
import android.os.UserHandle;
import android.os.WorkSource;
import android.os.WorkSource;
@@ -164,6 +165,10 @@ class PackageDexOptimizer {
            }
            }


            for (String path : paths) {
            for (String path : paths) {
                if (useProfiles && isUsedByOtherApps(path)) {
                    // We cannot use profile guided compilation if the apk was used by another app.
                    useProfiles = false;
                }
                int dexoptNeeded;
                int dexoptNeeded;


                try {
                try {
@@ -204,8 +209,10 @@ class PackageDexOptimizer {
                        + " vmSafeMode=" + vmSafeMode + " debuggable=" + debuggable
                        + " vmSafeMode=" + vmSafeMode + " debuggable=" + debuggable
                        + " extractOnly=" + extractOnly + " oatDir = " + oatDir);
                        + " extractOnly=" + extractOnly + " oatDir = " + oatDir);
                final int sharedGid = UserHandle.getSharedAppGid(pkg.applicationInfo.uid);
                final int sharedGid = UserHandle.getSharedAppGid(pkg.applicationInfo.uid);
                // Profile guide compiled oat files should not be public.
                final boolean isPublic = !pkg.isForwardLocked() && !useProfiles;
                final int dexFlags = adjustDexoptFlags(
                final int dexFlags = adjustDexoptFlags(
                        (!pkg.isForwardLocked() ? DEXOPT_PUBLIC : 0)
                        ( isPublic ? DEXOPT_PUBLIC : 0)
                        | (vmSafeMode ? DEXOPT_SAFEMODE : 0)
                        | (vmSafeMode ? DEXOPT_SAFEMODE : 0)
                        | (debuggable ? DEXOPT_DEBUGGABLE : 0)
                        | (debuggable ? DEXOPT_DEBUGGABLE : 0)
                        | (extractOnly ? DEXOPT_EXTRACTONLY : 0)
                        | (extractOnly ? DEXOPT_EXTRACTONLY : 0)
@@ -275,6 +282,25 @@ class PackageDexOptimizer {
        mSystemReady = true;
        mSystemReady = true;
    }
    }


    private boolean isUsedByOtherApps(String apkPath) {
        try {
            apkPath = new File(apkPath).getCanonicalPath();
        } catch (IOException e) {
            // Log an error but continue without it.
            Slog.w(TAG, "Failed to get canonical path", e);
        }
        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;
    }

    /**
    /**
     * A specialized PackageDexOptimizer that overrides already-installed checks, forcing a
     * A specialized PackageDexOptimizer that overrides already-installed checks, forcing a
     * dexopt path.
     * dexopt path.