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

Commit 539128f6 authored by Calin Juravle's avatar Calin Juravle Committed by Android (Google) Code Review
Browse files

Merge "Keep track of protected data dirs in DexManager" into oc-dev

parents 3c0f1f1a adbadd55
Loading
Loading
Loading
Loading
+5 −2
Original line number Diff line number Diff line
@@ -22,6 +22,7 @@ import android.content.pm.ApplicationInfo;
import android.content.pm.PackageInfo;
import android.content.pm.PackageParser;
import android.os.Environment;
import android.os.FileUtils;
import android.os.PowerManager;
import android.os.UserHandle;
import android.os.WorkSource;
@@ -259,9 +260,11 @@ public class PackageDexOptimizer {
        // Get the dexopt flags after getRealCompilerFilter to make sure we get the correct flags.
        int dexoptFlags = getDexFlags(info, compilerFilter) | DEXOPT_SECONDARY_DEX;
        // Check the app storage and add the appropriate flags.
        if (info.dataDir.equals(info.deviceProtectedDataDir)) {
        if (info.deviceProtectedDataDir != null &&
                FileUtils.contains(info.deviceProtectedDataDir, path)) {
            dexoptFlags |= DEXOPT_STORAGE_DE;
        } else if (info.dataDir.equals(info.credentialProtectedDataDir)) {
        } else if (info.credentialProtectedDataDir != null &&
                FileUtils.contains(info.credentialProtectedDataDir, path)) {
            dexoptFlags |= DEXOPT_STORAGE_CE;
        } else {
            Slog.e(TAG, "Could not infer CE/DE storage for package " + info.packageName);
+36 −16
Original line number Diff line number Diff line
@@ -19,7 +19,7 @@ package com.android.server.pm.dex;
import android.content.pm.ApplicationInfo;
import android.content.pm.IPackageManager;
import android.content.pm.PackageInfo;
import android.content.pm.PackageParser;
import android.os.FileUtils;
import android.os.RemoteException;
import android.os.storage.StorageManager;
import android.os.UserHandle;
@@ -93,7 +93,7 @@ public class DexManager {
     * Note that this method is invoked when apps load dex files and it should
     * return as fast as possible.
     *
     * @param loadingPackage the package performing the load
     * @param loadingAppInfo the package performing the load
     * @param dexPaths the list of dex files being loaded
     * @param loaderIsa the ISA of the app loading the dex files
     * @param loaderUserId the user id which runs the code loading the dex files
@@ -191,8 +191,7 @@ public class DexManager {
            throw new IllegalArgumentException(
                "notifyPackageInstalled called with USER_ALL");
        }
        cachePackageCodeLocation(pi.packageName, pi.applicationInfo.sourceDir,
                pi.applicationInfo.splitSourceDirs, pi.applicationInfo.dataDir, userId);
        cachePackageInfo(pi, userId);
    }

    /**
@@ -231,15 +230,34 @@ public class DexManager {
        }
    }

    public void cachePackageCodeLocation(String packageName, String baseCodePath,
            String[] splitCodePaths, String dataDir, int userId) {
    /**
     * Caches the code location from the given package info.
     */
    private void cachePackageInfo(PackageInfo pi, int userId) {
        ApplicationInfo ai = pi.applicationInfo;
        String[] dataDirs = new String[] {ai.dataDir, ai.deviceProtectedDataDir,
                ai.credentialProtectedDataDir};
        cachePackageCodeLocation(pi.packageName, ai.sourceDir, ai.splitSourceDirs,
                dataDirs, userId);
    }

    private void cachePackageCodeLocation(String packageName, String baseCodePath,
            String[] splitCodePaths, String[] dataDirs, int userId) {
        PackageCodeLocations pcl = putIfAbsent(mPackageCodeLocationsCache, packageName,
                new PackageCodeLocations(packageName, baseCodePath, splitCodePaths));
        pcl.updateCodeLocation(baseCodePath, splitCodePaths);
        if (dataDirs != null) {
            for (String dataDir : dataDirs) {
                // The set of data dirs includes deviceProtectedDataDir and
                // credentialProtectedDataDir which might be null for shared
                // libraries. Currently we don't track these but be lenient
                // and check in case we ever decide to store their usage data.
                if (dataDir != null) {
                    pcl.mergeAppDataDirs(dataDir, userId);
                }
            }
        }
    }

    private void loadInternal(Map<Integer, List<PackageInfo>> existingPackages) {
        Map<String, Set<Integer>> packageToUsersMap = new HashMap<>();
@@ -250,8 +268,7 @@ public class DexManager {
            int userId = entry.getKey();
            for (PackageInfo pi : packageInfoList) {
                // Cache the code locations.
                cachePackageCodeLocation(pi.packageName, pi.applicationInfo.sourceDir,
                        pi.applicationInfo.splitSourceDirs, pi.applicationInfo.dataDir, userId);
                cachePackageInfo(pi, userId);

                // Cache a map from package name to the set of user ids who installed the package.
                // We will use it to sync the data and remove obsolete entries from
@@ -329,6 +346,7 @@ public class DexManager {
                mPackageDexUsage.removeUserPackage(packageName, dexUseInfo.getOwnerUserId());
                continue;
            }

            int result = pdo.dexOptSecondaryDexPath(pkg.applicationInfo, dexPath,
                    dexUseInfo.getLoaderIsas(), compilerFilter, dexUseInfo.isUsedByOtherApps());
            success = success && (result != PackageDexOptimizer.DEX_OPT_FAILED);
@@ -350,7 +368,7 @@ public class DexManager {
            // Nothing to reconcile.
            return;
        }
        Set<String> dexFilesToRemove = new HashSet<>();

        boolean updated = false;
        for (Map.Entry<String, DexUseInfo> entry : useInfo.getDexUseInfoMap().entrySet()) {
            String dexPath = entry.getKey();
@@ -378,14 +396,16 @@ public class DexManager {
            }
            ApplicationInfo info = pkg.applicationInfo;
            int flags = 0;
            if (info.dataDir.equals(info.deviceProtectedDataDir)) {
            if (info.deviceProtectedDataDir != null &&
                    FileUtils.contains(info.deviceProtectedDataDir, dexPath)) {
                flags |= StorageManager.FLAG_STORAGE_DE;
            } else if (info.dataDir.equals(info.credentialProtectedDataDir)) {
            } else if (info.credentialProtectedDataDir!= null &&
                    FileUtils.contains(info.credentialProtectedDataDir, dexPath)) {
                flags |= StorageManager.FLAG_STORAGE_CE;
            } else {
                Slog.e(TAG, "Could not infer CE/DE storage for package " + info.packageName);
                updated = mPackageDexUsage.removeUserPackage(
                        packageName, dexUseInfo.getOwnerUserId()) || updated;
                Slog.e(TAG, "Could not infer CE/DE storage for path " + dexPath);
                updated = mPackageDexUsage.removeDexFile(
                        packageName, dexPath, dexUseInfo.getOwnerUserId()) || updated;
                continue;
            }

+22 −0
Original line number Diff line number Diff line
@@ -360,6 +360,19 @@ public class DexManagerTests {
        assertNull(mDexManager.getPackageUseInfo(frameworkDex));
    }

    @Test
    public void testNotifySecondaryFromProtected() {
        // Foo loads its own secondary files.
        List<String> fooSecondaries = mFooUser0.getSecondaryDexPathsFromProtectedDirs();
        notifyDexLoad(mFooUser0, fooSecondaries, mUser0);

        PackageUseInfo pui = getPackageUseInfo(mFooUser0);
        assertNotNull(pui);
        assertFalse(pui.isUsedByOtherApps());
        assertEquals(fooSecondaries.size(), pui.getDexUseInfoMap().size());
        assertSecondaryUse(mFooUser0, pui, fooSecondaries, /*isUsedByOtherApps*/false, mUser0);
    }

    private void assertSecondaryUse(TestData testData, PackageUseInfo pui,
            List<String> secondaries, boolean isUsedByOtherApps, int ownerUserId) {
        for (String dex : secondaries) {
@@ -394,6 +407,8 @@ public class DexManagerTests {
        ai.setBaseCodePath(codeDir + "/base.dex");
        ai.setSplitCodePaths(new String[] {codeDir + "/split-1.dex", codeDir + "/split-2.dex"});
        ai.dataDir = "/data/user/" + userId + "/" + packageName;
        ai.deviceProtectedDataDir = "/data/user_de/" + userId + "/" + packageName;
        ai.credentialProtectedDataDir = "/data/user_ce/" + userId + "/" + packageName;
        ai.packageName = packageName;
        return ai;
    }
@@ -426,6 +441,13 @@ public class DexManagerTests {
            return paths;
        }

        List<String> getSecondaryDexPathsFromProtectedDirs() {
            List<String> paths = new ArrayList<>();
            paths.add(mPackageInfo.applicationInfo.dataDir + "/secondary6.dex");
            paths.add(mPackageInfo.applicationInfo.dataDir + "/secondary7.dex");
            return paths;
        }

        List<String> getBaseAndSplitDexPaths() {
            List<String> paths = new ArrayList<>();
            paths.add(mPackageInfo.applicationInfo.sourceDir);