Loading services/core/java/com/android/server/pm/PackageDexOptimizer.java +5 −2 Original line number Diff line number Diff line Loading @@ -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; Loading Loading @@ -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); Loading services/core/java/com/android/server/pm/dex/DexManager.java +36 −16 Original line number Diff line number Diff line Loading @@ -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; Loading Loading @@ -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 Loading Loading @@ -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); } /** Loading Loading @@ -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<>(); Loading @@ -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 Loading Loading @@ -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); Loading @@ -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(); Loading Loading @@ -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; } Loading services/tests/servicestests/src/com/android/server/pm/dex/DexManagerTests.java +22 −0 Original line number Diff line number Diff line Loading @@ -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) { Loading Loading @@ -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; } Loading Loading @@ -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); Loading Loading
services/core/java/com/android/server/pm/PackageDexOptimizer.java +5 −2 Original line number Diff line number Diff line Loading @@ -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; Loading Loading @@ -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); Loading
services/core/java/com/android/server/pm/dex/DexManager.java +36 −16 Original line number Diff line number Diff line Loading @@ -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; Loading Loading @@ -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 Loading Loading @@ -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); } /** Loading Loading @@ -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<>(); Loading @@ -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 Loading Loading @@ -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); Loading @@ -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(); Loading Loading @@ -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; } Loading
services/tests/servicestests/src/com/android/server/pm/dex/DexManagerTests.java +22 −0 Original line number Diff line number Diff line Loading @@ -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) { Loading Loading @@ -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; } Loading Loading @@ -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); Loading