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

This commit is contained in:
Calin Juravle
2017-04-06 15:54:58 +00:00
committed by Android (Google) Code Review
3 changed files with 63 additions and 18 deletions

View File

@@ -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);

View File

@@ -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;
}

View File

@@ -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);