summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--services/core/java/com/android/server/pm/dex/DexManager.java5
-rw-r--r--services/core/java/com/android/server/pm/dex/PackageDexUsage.java32
-rw-r--r--services/tests/servicestests/src/com/android/server/pm/dex/PackageDexUsageTests.java43
3 files changed, 70 insertions, 10 deletions
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 9f2ec47335f3..e8765ad973f3 100644
--- a/services/core/java/com/android/server/pm/dex/DexManager.java
+++ b/services/core/java/com/android/server/pm/dex/DexManager.java
@@ -45,6 +45,7 @@ import dalvik.system.VMRuntime;
import java.io.File;
import java.io.IOException;
+import java.util.ArrayList;
import java.util.Arrays;
import java.util.Collection;
import java.util.Collections;
@@ -353,7 +354,9 @@ public class DexManager {
try {
mPackageDexUsage.read();
- mPackageDexUsage.syncData(packageToUsersMap, packageToCodePaths);
+ List<String> packagesToKeepDataAbout = new ArrayList<>();
+ mPackageDexUsage.syncData(
+ packageToUsersMap, packageToCodePaths, packagesToKeepDataAbout);
} catch (Exception e) {
mPackageDexUsage.clear();
Slog.w(TAG, "Exception while loading package dex usage. "
diff --git a/services/core/java/com/android/server/pm/dex/PackageDexUsage.java b/services/core/java/com/android/server/pm/dex/PackageDexUsage.java
index 1a3c18f61333..7ac09e373d20 100644
--- a/services/core/java/com/android/server/pm/dex/PackageDexUsage.java
+++ b/services/core/java/com/android/server/pm/dex/PackageDexUsage.java
@@ -474,13 +474,19 @@ public class PackageDexUsage extends AbstractStatsBase<Void> {
* Syncs the existing data with the set of available packages by removing obsolete entries.
*/
/*package*/ void syncData(Map<String, Set<Integer>> packageToUsersMap,
- Map<String, Set<String>> packageToCodePaths) {
+ Map<String, Set<String>> packageToCodePaths,
+ List<String> packagesToKeepDataAbout) {
synchronized (mPackageUseInfoMap) {
Iterator<Map.Entry<String, PackageUseInfo>> pIt =
mPackageUseInfoMap.entrySet().iterator();
while (pIt.hasNext()) {
Map.Entry<String, PackageUseInfo> pEntry = pIt.next();
String packageName = pEntry.getKey();
+ if (packagesToKeepDataAbout.contains(packageName)) {
+ // This is a package for which we should keep the data even if it's not
+ // in the list of user packages.
+ continue;
+ }
PackageUseInfo packageUseInfo = pEntry.getValue();
Set<Integer> users = packageToUsersMap.get(packageName);
if (users == null) {
@@ -501,11 +507,27 @@ public class PackageDexUsage extends AbstractStatsBase<Void> {
// Sync the code paths.
Set<String> codePaths = packageToCodePaths.get(packageName);
- Iterator<Map.Entry<String, Set<String>>> codeIt =
+
+ Iterator<Map.Entry<String, Set<String>>> recordedIt =
packageUseInfo.mPrimaryCodePaths.entrySet().iterator();
- while (codeIt.hasNext()) {
- if (!codePaths.contains(codeIt.next().getKey())) {
- codeIt.remove();
+ while (recordedIt.hasNext()) {
+ Map.Entry<String, Set<String>> entry = recordedIt.next();
+ String recordedCodePath = entry.getKey();
+ if (!codePaths.contains(recordedCodePath)) {
+ // Clean up a non existing code path.
+ recordedIt.remove();
+ } else {
+ // Clean up a non existing loading package.
+ Set<String> recordedLoadingPackages = entry.getValue();
+ Iterator<String> recordedLoadingPackagesIt =
+ recordedLoadingPackages.iterator();
+ while (recordedLoadingPackagesIt.hasNext()) {
+ String recordedLoadingPackage = recordedLoadingPackagesIt.next();
+ if (!packagesToKeepDataAbout.contains(recordedLoadingPackage)
+ && !packageToUsersMap.containsKey(recordedLoadingPackage)) {
+ recordedLoadingPackagesIt.remove();
+ }
+ }
}
}
diff --git a/services/tests/servicestests/src/com/android/server/pm/dex/PackageDexUsageTests.java b/services/tests/servicestests/src/com/android/server/pm/dex/PackageDexUsageTests.java
index 08fc87758f57..2829fa7bf83f 100644
--- a/services/tests/servicestests/src/com/android/server/pm/dex/PackageDexUsageTests.java
+++ b/services/tests/servicestests/src/com/android/server/pm/dex/PackageDexUsageTests.java
@@ -282,7 +282,7 @@ public class PackageDexUsageTests {
Map<String, Set<String>> packageToCodePaths = new HashMap<>();
packageToCodePaths.put(mBarBaseUser0.mPackageName,
new HashSet<>(Arrays.asList(mBarBaseUser0.mDexFile)));
- mPackageDexUsage.syncData(packageToUsersMap, packageToCodePaths);
+ mPackageDexUsage.syncData(packageToUsersMap, packageToCodePaths, new ArrayList<String>());
// Assert that only user 1 files are there.
assertPackageDexUsage(mBarBaseUser0, mBarSecondary2User1);
@@ -290,6 +290,41 @@ public class PackageDexUsageTests {
}
@Test
+ public void testSyncDataKeepPackages() {
+ PackageDexUsage packageDexUsage = new PackageDexUsage();
+ // Write the record we want to keep and which won't be keep by default.
+ Set<String> fooUsers = new HashSet<>(Arrays.asList(
+ new String[] {mFooBaseUser0.mPackageName}));
+ assertTrue(record(packageDexUsage, mFooBaseUser0, fooUsers));
+ // Write a record that would be kept by default.
+ Set<String> barUsers = new HashSet<>(Arrays.asList(
+ new String[] {"another.package", mFooBaseUser0.mPackageName}));
+ assertTrue(record(packageDexUsage, mBarBaseUser0, barUsers));
+
+ // Construct the user packages and their code paths (things that will be
+ // kept by default during sync).
+ Map<String, Set<Integer>> packageToUsersMap = new HashMap<>();
+ packageToUsersMap.put(mBarBaseUser0.mPackageName,
+ new HashSet<>(Arrays.asList(mBarBaseUser0.mOwnerUserId)));
+ Map<String, Set<String>> packageToCodePaths = new HashMap<>();
+ packageToCodePaths.put(mBarBaseUser0.mPackageName,
+ new HashSet<>(Arrays.asList(mBarBaseUser0.mDexFile)));
+
+ // Sync data.
+ List<String> keepData = new ArrayList<String>();
+ keepData.add(mFooBaseUser0.mPackageName);
+ packageDexUsage.syncData(packageToUsersMap, packageToCodePaths, keepData);
+
+ // Assert that both packages are kept
+ assertPackageDexUsage(packageDexUsage, fooUsers, mFooBaseUser0);
+ // "another.package" should not be in the loading packages after sync.
+ Set<String> expectedBarUsers = new HashSet<>(Arrays.asList(
+ new String[] {mFooBaseUser0.mPackageName}));
+ assertPackageDexUsage(packageDexUsage, expectedBarUsers,
+ mBarBaseUser0.updateUsedBy(mFooBaseUser0.mPackageName));
+ }
+
+ @Test
public void testRemovePackage() {
// Record Bar secondaries for two different users.
assertTrue(record(mBarSecondary1User0));
@@ -501,7 +536,7 @@ public class PackageDexUsageTests {
new HashSet<>(Arrays.asList(mFooSplit2UsedByOtherApps0.mOwnerUserId)));
// Sync the data.
- packageDexUsage.syncData(packageToUsersMap, packageToCodePaths);
+ packageDexUsage.syncData(packageToUsersMap, packageToCodePaths, new ArrayList<>());
// Assert foo code paths.
assertPackageDexUsage(
@@ -654,9 +689,9 @@ public class PackageDexUsageTests {
mPrimaryOrSplit, mUsedBy, newContext);
}
- private TestData updateUseByOthers(boolean newUsedByOthers) {
+ private TestData updateUsedBy(String newUsedBy) {
return new TestData(mPackageName, mDexFile, mOwnerUserId, mLoaderIsa,
- mPrimaryOrSplit, mUsedBy, mClassLoaderContext);
+ mPrimaryOrSplit, newUsedBy, mClassLoaderContext);
}
private boolean isUsedByOtherApps() {