diff options
author | 2017-04-06 15:54:58 +0000 | |
---|---|---|
committer | 2017-04-06 15:55:04 +0000 | |
commit | 539128f6d652d0a38cede9cb4dbb9888f89ffbcf (patch) | |
tree | e4a155472073f8c6a72d1125f7db4dcc645a0582 | |
parent | 3c0f1f1aa2dc4d6a3b73e535ef13ad851b7bbbfb (diff) | |
parent | adbadd5577d2b1291d10146b6ffb5577cf236528 (diff) |
Merge "Keep track of protected data dirs in DexManager" into oc-dev
3 files changed, 63 insertions, 18 deletions
diff --git a/services/core/java/com/android/server/pm/PackageDexOptimizer.java b/services/core/java/com/android/server/pm/PackageDexOptimizer.java index acbd446a967f..781be34828ad 100644 --- a/services/core/java/com/android/server/pm/PackageDexOptimizer.java +++ b/services/core/java/com/android/server/pm/PackageDexOptimizer.java @@ -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); diff --git a/services/core/java/com/android/server/pm/dex/DexManager.java b/services/core/java/com/android/server/pm/dex/DexManager.java index c693a475ed59..3d7cedce522a 100644 --- a/services/core/java/com/android/server/pm/dex/DexManager.java +++ b/services/core/java/com/android/server/pm/dex/DexManager.java @@ -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,13 +230,32 @@ 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 (dataDir != null) { - pcl.mergeAppDataDirs(dataDir, userId); + 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); + } + } } } @@ -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; } diff --git a/services/tests/servicestests/src/com/android/server/pm/dex/DexManagerTests.java b/services/tests/servicestests/src/com/android/server/pm/dex/DexManagerTests.java index 72fb78e89ea2..afc0f67fe993 100644 --- a/services/tests/servicestests/src/com/android/server/pm/dex/DexManagerTests.java +++ b/services/tests/servicestests/src/com/android/server/pm/dex/DexManagerTests.java @@ -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); |