summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
author Calin Juravle <calin@google.com> 2020-03-29 16:53:21 -0700
committer Calin Juravle <calin@google.com> 2020-04-01 12:17:47 -0700
commit33fc19ce557ffbb7e451c2f89749c1842c88dc9c (patch)
treea24b0bbecac26e6ddb5be9aa5ae99fd38c721782
parentc6f4f74723737db10a79865c6686abc28cb223b4 (diff)
Remove support for PackageDexUsage version 1
PackageVersion version 1 was indroduce in Nougat. Since then, all devices should have updated to version 2 which was introduced in O. This simplifies the logic in preparation for adding support for system server jars. Test: atest DexManagerTests PackageDexUsageTests Bug: 148774920 Change-Id: Ib546ed12c5341d01fb12545cd98598b4cf2c5051
-rw-r--r--services/core/java/com/android/server/pm/PackageDexOptimizer.java3
-rw-r--r--services/core/java/com/android/server/pm/dex/DexManager.java2
-rw-r--r--services/core/java/com/android/server/pm/dex/PackageDexUsage.java161
-rw-r--r--services/tests/servicestests/src/com/android/server/pm/dex/PackageDexUsageTests.java104
4 files changed, 51 insertions, 219 deletions
diff --git a/services/core/java/com/android/server/pm/PackageDexOptimizer.java b/services/core/java/com/android/server/pm/PackageDexOptimizer.java
index e625aeffc0c6..e7d0c41c0fea 100644
--- a/services/core/java/com/android/server/pm/PackageDexOptimizer.java
+++ b/services/core/java/com/android/server/pm/PackageDexOptimizer.java
@@ -401,7 +401,8 @@ public class PackageDexOptimizer {
return DEX_OPT_FAILED;
}
String classLoaderContext = null;
- if (dexUseInfo.isUnknownClassLoaderContext() || dexUseInfo.isVariableClassLoaderContext()) {
+ if (dexUseInfo.isUnsupportedClassLoaderContext()
+ || dexUseInfo.isVariableClassLoaderContext()) {
// If we have an unknown (not yet set), or a variable class loader chain. Just extract
// the dex file.
compilerFilter = "extract";
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 117cc5e8eb80..5ba1996ed3c9 100644
--- a/services/core/java/com/android/server/pm/dex/DexManager.java
+++ b/services/core/java/com/android/server/pm/dex/DexManager.java
@@ -563,7 +563,7 @@ public class DexManager {
boolean newUpdate = mPackageDexUsage.record(searchResult.mOwningPackageName,
dexPath, userId, isa, isUsedByOtherApps, /*primaryOrSplit*/ false,
searchResult.mOwningPackageName,
- PackageDexUsage.UNKNOWN_CLASS_LOADER_CONTEXT);
+ PackageDexUsage.VARIABLE_CLASS_LOADER_CONTEXT);
update |= newUpdate;
}
if (update) {
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 08763e729c71..8819a0fe439b 100644
--- a/services/core/java/com/android/server/pm/dex/PackageDexUsage.java
+++ b/services/core/java/com/android/server/pm/dex/PackageDexUsage.java
@@ -51,25 +51,21 @@ import java.util.Set;
* Stat file which store usage information about dex files.
*/
public class PackageDexUsage extends AbstractStatsBase<Void> {
- private final static String TAG = "PackageDexUsage";
+ private static final String TAG = "PackageDexUsage";
- // We support previous version to ensure that the usage list remains valid cross OTAs.
- private final static int PACKAGE_DEX_USAGE_SUPPORTED_VERSION_1 = 1;
- // Version 2 added:
- // - the list of packages that load the dex files
- // - class loader contexts for secondary dex files
- // - usage for all code paths (including splits)
- private final static int PACKAGE_DEX_USAGE_SUPPORTED_VERSION_2 = 2;
+ // We are currently at version 2.
+ // Version 1 was introduced in Nougat and Version 2 in Oreo.
+ // We dropped version 1 support in R since all devices should have updated
+ // already.
+ private static final int PACKAGE_DEX_USAGE_VERSION = 2;
- private final static int PACKAGE_DEX_USAGE_VERSION = PACKAGE_DEX_USAGE_SUPPORTED_VERSION_2;
-
- private final static String PACKAGE_DEX_USAGE_VERSION_HEADER =
+ private static final String PACKAGE_DEX_USAGE_VERSION_HEADER =
"PACKAGE_MANAGER__PACKAGE_DEX_USAGE__";
- private final static String SPLIT_CHAR = ",";
- private final static String CODE_PATH_LINE_CHAR = "+";
- private final static String DEX_LINE_CHAR = "#";
- private final static String LOADING_PACKAGE_CHAR = "@";
+ private static final String SPLIT_CHAR = ",";
+ private static final String CODE_PATH_LINE_CHAR = "+";
+ private static final String DEX_LINE_CHAR = "#";
+ private static final String LOADING_PACKAGE_CHAR = "@";
// One of the things we record about dex files is the class loader context that was used to
// load them. That should be stable but if it changes we don't keep track of variable contexts.
@@ -77,10 +73,6 @@ public class PackageDexUsage extends AbstractStatsBase<Void> {
// skip optimizations on that dex files.
/*package*/ static final String VARIABLE_CLASS_LOADER_CONTEXT =
"=VariableClassLoaderContext=";
- // The markers used for unknown class loader contexts. This can happen if the dex file was
- // recorded in a previous version and we didn't have a chance to update its usage.
- /*package*/ static final String UNKNOWN_CLASS_LOADER_CONTEXT =
- "=UnknownClassLoaderContext=";
// The marker used for unsupported class loader contexts (no longer written, may occur in old
// files so discarded on read). Note: this matches
@@ -339,7 +331,9 @@ public class PackageDexUsage extends AbstractStatsBase<Void> {
version = Integer.parseInt(
versionLine.substring(PACKAGE_DEX_USAGE_VERSION_HEADER.length()));
if (!isSupportedVersion(version)) {
- throw new IllegalStateException("Unexpected version: " + version);
+ Slog.w(TAG, "Unexpected package-dex-use version: " + version
+ + ". Not reading from it");
+ return;
}
}
@@ -377,9 +371,8 @@ public class PackageDexUsage extends AbstractStatsBase<Void> {
throw new IllegalStateException("Invalid PackageDexUsage line: " + line);
}
- // In version 2 we added the loading packages and class loader context.
- Set<String> loadingPackages = maybeReadLoadingPackages(in, version);
- String classLoaderContext = maybeReadClassLoaderContext(in, version);
+ Set<String> loadingPackages = readLoadingPackages(in, version);
+ String classLoaderContext = readClassLoaderContext(in, version);
if (UNSUPPORTED_CLASS_LOADER_CONTEXT.equals(classLoaderContext)) {
// We used to record use of unsupported class loaders, but we no longer do.
@@ -410,34 +403,16 @@ public class PackageDexUsage extends AbstractStatsBase<Void> {
}
currentPackageData.mDexUseInfoMap.put(dexPath, dexUseInfo);
} else if (line.startsWith(CODE_PATH_LINE_CHAR)) {
- // This is a code path used by other apps line.
- if (version < PACKAGE_DEX_USAGE_SUPPORTED_VERSION_2) {
- throw new IllegalArgumentException("Unexpected code path line when parsing " +
- "PackageDexUseData: " + line);
- }
-
// Expects 2 lines:
// +code_paths
// @loading_packages
String codePath = line.substring(CODE_PATH_LINE_CHAR.length());
- Set<String> loadingPackages = maybeReadLoadingPackages(in, version);
+ Set<String> loadingPackages = readLoadingPackages(in, version);
currentPackageData.mCodePathsUsedByOtherApps.put(codePath, loadingPackages);
} else {
// This is a package line.
- if (version >= PACKAGE_DEX_USAGE_SUPPORTED_VERSION_2) {
- currentPackage = line;
- currentPackageData = new PackageUseInfo();
- } else {
- // Old version (<2)
- // We expect it to be: `packageName,isUsedByOtherApps`.
- String[] elems = line.split(SPLIT_CHAR);
- if (elems.length != 2) {
- throw new IllegalStateException("Invalid PackageDexUsage line: " + line);
- }
- currentPackage = elems[0];
- currentPackageData = new PackageUseInfo();
- currentPackageData.mUsedByOtherAppsBeforeUpgrade = readBoolean(elems[1]);
- }
+ currentPackage = line;
+ currentPackageData = new PackageUseInfo();
data.put(currentPackage, currentPackageData);
}
}
@@ -449,45 +424,33 @@ public class PackageDexUsage extends AbstractStatsBase<Void> {
}
/**
- * Reads the class loader context encoding from the buffer {@code in} if
- * {@code version} is at least {PACKAGE_DEX_USAGE_VERSION}.
+ * Reads the class loader context encoding from the buffer {@code in}.
*/
- private String maybeReadClassLoaderContext(BufferedReader in, int version) throws IOException {
- String context = null;
- if (version >= PACKAGE_DEX_USAGE_SUPPORTED_VERSION_2) {
- context = in.readLine();
- if (context == null) {
- throw new IllegalStateException("Could not find the classLoaderContext line.");
- }
+ private String readClassLoaderContext(BufferedReader in, int version) throws IOException {
+ String context = in.readLine();
+ if (context == null) {
+ throw new IllegalStateException("Could not find the classLoaderContext line.");
}
- // The context might be empty if we didn't have the chance to update it after a version
- // upgrade. In this case return the special marker so that we recognize this is an unknown
- // context.
- return context == null ? UNKNOWN_CLASS_LOADER_CONTEXT : context;
+ return context;
}
/**
- * Reads the list of loading packages from the buffer {@code in} if
- * {@code version} is at least {PACKAGE_DEX_USAGE_SUPPORTED_VERSION_2}.
+ * Reads the list of loading packages from the buffer {@code in}.
*/
- private Set<String> maybeReadLoadingPackages(BufferedReader in, int version)
+ private Set<String> readLoadingPackages(BufferedReader in, int version)
throws IOException {
- if (version >= PACKAGE_DEX_USAGE_SUPPORTED_VERSION_2) {
- String line = in.readLine();
- if (line == null) {
- throw new IllegalStateException("Could not find the loadingPackages line.");
- }
- // We expect that most of the times the list of loading packages will be empty.
- if (line.length() == LOADING_PACKAGE_CHAR.length()) {
- return Collections.emptySet();
- } else {
- Set<String> result = new HashSet<>();
- Collections.addAll(result,
- line.substring(LOADING_PACKAGE_CHAR.length()).split(SPLIT_CHAR));
- return result;
- }
- } else {
+ String line = in.readLine();
+ if (line == null) {
+ throw new IllegalStateException("Could not find the loadingPackages line.");
+ }
+ // We expect that most of the times the list of loading packages will be empty.
+ if (line.length() == LOADING_PACKAGE_CHAR.length()) {
return Collections.emptySet();
+ } else {
+ Set<String> result = new HashSet<>();
+ Collections.addAll(result,
+ line.substring(LOADING_PACKAGE_CHAR.length()).split(SPLIT_CHAR));
+ return result;
}
}
@@ -501,8 +464,7 @@ public class PackageDexUsage extends AbstractStatsBase<Void> {
}
private boolean isSupportedVersion(int version) {
- return version == PACKAGE_DEX_USAGE_SUPPORTED_VERSION_1
- || version == PACKAGE_DEX_USAGE_SUPPORTED_VERSION_2;
+ return version == PACKAGE_DEX_USAGE_VERSION;
}
/**
@@ -544,14 +506,7 @@ public class PackageDexUsage extends AbstractStatsBase<Void> {
}
}
- // In case the package was marked as used by other apps in a previous version
- // propagate the flag to all the code paths.
- // See mUsedByOtherAppsBeforeUpgrade docs on why it is important to do it.
- if (packageUseInfo.mUsedByOtherAppsBeforeUpgrade) {
- for (String codePath : codePaths) {
- packageUseInfo.mergeCodePathUsedByOtherApps(codePath, true, null, null);
- }
- } else if (!packageUseInfo.isAnyCodePathUsedByOtherApps()
+ if (!packageUseInfo.isAnyCodePathUsedByOtherApps()
&& packageUseInfo.mDexUseInfoMap.isEmpty()) {
// The package is not used by other apps and we removed all its dex files
// records. Remove the entire package record as well.
@@ -718,19 +673,6 @@ public class PackageDexUsage extends AbstractStatsBase<Void> {
// Map dex paths to their data (isUsedByOtherApps, owner id, loader isa).
private final Map<String, DexUseInfo> mDexUseInfoMap;
- // Keeps track of whether or not this package was used by other apps before
- // we upgraded to VERSION 4 which records the info for each code path separately.
- // This is unwanted complexity but without it we risk to profile guide compile
- // something that supposed to be shared. For example:
- // 1) we determine that chrome is used by another app
- // 2) we take an OTA which upgrades the way we keep track of usage data
- // 3) chrome doesn't get used until the background job executes
- // 4) as part of the backgound job we now think that chrome is not used by others
- // and we speed-profile.
- // 5) as a result the next time someone uses chrome it will extract from apk since
- // the compiled code will be private.
- private boolean mUsedByOtherAppsBeforeUpgrade;
-
/*package*/ PackageUseInfo() {
mCodePathsUsedByOtherApps = new HashMap<>();
mDexUseInfoMap = new HashMap<>();
@@ -790,10 +732,6 @@ public class PackageDexUsage extends AbstractStatsBase<Void> {
* Returns whether or not there was an update.
*/
/*package*/ boolean clearCodePathUsedByOtherApps() {
- // Update mUsedByOtherAppsBeforeUpgrade as well to be consistent with
- // the new data. This is not saved to disk so we don't need to return it.
- mUsedByOtherAppsBeforeUpgrade = true;
-
if (mCodePathsUsedByOtherApps.isEmpty()) {
return false;
} else {
@@ -847,11 +785,9 @@ public class PackageDexUsage extends AbstractStatsBase<Void> {
boolean updateLoadingPackages = mLoadingPackages.addAll(dexUseInfo.mLoadingPackages);
String oldClassLoaderContext = mClassLoaderContext;
- if (isUnknownOrUnsupportedContext(mClassLoaderContext)) {
- // Can happen if we read a previous version.
+ if (isUnsupportedContext(mClassLoaderContext)) {
mClassLoaderContext = dexUseInfo.mClassLoaderContext;
- } else if (!isUnknownOrUnsupportedContext(dexUseInfo.mClassLoaderContext)
- && !Objects.equals(mClassLoaderContext, dexUseInfo.mClassLoaderContext)) {
+ } else if (!Objects.equals(mClassLoaderContext, dexUseInfo.mClassLoaderContext)) {
// We detected a context change.
mClassLoaderContext = VARIABLE_CLASS_LOADER_CONTEXT;
}
@@ -862,11 +798,8 @@ public class PackageDexUsage extends AbstractStatsBase<Void> {
|| !Objects.equals(oldClassLoaderContext, mClassLoaderContext);
}
- private static boolean isUnknownOrUnsupportedContext(String context) {
- // TODO: Merge UNKNOWN_CLASS_LOADER_CONTEXT & UNSUPPORTED_CLASS_LOADER_CONTEXT cases
- // into UNSUPPORTED_CLASS_LOADER_CONTEXT.
- return UNKNOWN_CLASS_LOADER_CONTEXT.equals(context)
- || UNSUPPORTED_CLASS_LOADER_CONTEXT.equals(context);
+ private static boolean isUnsupportedContext(String context) {
+ return UNSUPPORTED_CLASS_LOADER_CONTEXT.equals(context);
}
public boolean isUsedByOtherApps() {
@@ -887,10 +820,8 @@ public class PackageDexUsage extends AbstractStatsBase<Void> {
public String getClassLoaderContext() { return mClassLoaderContext; }
- public boolean isUnknownClassLoaderContext() {
- // The class loader context may be unknown if we loaded the data from a previous version
- // which didn't save the context.
- return isUnknownOrUnsupportedContext(mClassLoaderContext);
+ public boolean isUnsupportedClassLoaderContext() {
+ return isUnsupportedContext(mClassLoaderContext);
}
public boolean isVariableClassLoaderContext() {
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 5df4509af885..f01ddfca15c6 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
@@ -421,44 +421,18 @@ public class PackageDexUsageTests {
}
@Test
- public void testRecordClassLoaderContextTransitionFromUnknown() {
- // Record a secondary dex file.
- TestData unknownContext = mFooSecondary1User0.updateClassLoaderContext(
- PackageDexUsage.UNKNOWN_CLASS_LOADER_CONTEXT);
- assertTrue(record(unknownContext));
-
- assertPackageDexUsage(null, unknownContext);
- writeAndReadBack();
- assertPackageDexUsage(null, unknownContext);
-
- // Now update the secondary dex record with a class loader context. This simulates the
- // version 2 to version 3 upgrade.
-
- assertTrue(record(mFooSecondary1User0));
-
- assertPackageDexUsage(null, mFooSecondary1User0);
- writeAndReadBack();
- assertPackageDexUsage(null, mFooSecondary1User0);
- }
-
- @Test
public void testDexUsageClassLoaderContext() {
final boolean isUsedByOtherApps = false;
final int userId = 0;
PackageDexUsage.DexUseInfo validContext = new DexUseInfo(isUsedByOtherApps, userId,
"valid_context", "arm");
- assertFalse(validContext.isUnknownClassLoaderContext());
+ assertFalse(validContext.isUnsupportedClassLoaderContext());
assertFalse(validContext.isVariableClassLoaderContext());
PackageDexUsage.DexUseInfo variableContext = new DexUseInfo(isUsedByOtherApps, userId,
PackageDexUsage.VARIABLE_CLASS_LOADER_CONTEXT, "arm");
- assertFalse(variableContext.isUnknownClassLoaderContext());
+ assertFalse(variableContext.isUnsupportedClassLoaderContext());
assertTrue(variableContext.isVariableClassLoaderContext());
-
- PackageDexUsage.DexUseInfo unknownContext = new DexUseInfo(isUsedByOtherApps, userId,
- PackageDexUsage.UNKNOWN_CLASS_LOADER_CONTEXT, "arm");
- assertTrue(unknownContext.isUnknownClassLoaderContext());
- assertFalse(unknownContext.isVariableClassLoaderContext());
}
@Test
@@ -482,80 +456,6 @@ public class PackageDexUsageTests {
assertPackageDexUsage(mBarBaseUser0);
}
- @Test
- public void testReadVersion1() {
- String isa = VMRuntime.getInstructionSet(Build.SUPPORTED_ABIS[0]);
- // Equivalent to
- // record(mFooSplit2UsedByOtherApps0);
- // record(mFooSecondary1User0);
- // record(mFooSecondary2UsedByOtherApps0);
- // record(mBarBaseUser0);
- // record(mBarSecondary1User0);
- String content = "PACKAGE_MANAGER__PACKAGE_DEX_USAGE__1\n"
- + "com.google.foo,1\n"
- + "#/data/user/0/com.google.foo/sec-1.dex\n"
- + "0,0," + isa + "\n"
- + "#/data/user/0/com.google.foo/sec-2.dex\n"
- + "0,1," + isa + "\n"
- + "com.google.bar,0\n"
- + "#/data/user/0/com.google.bar/sec-1.dex\n"
- + "0,0," + isa + "\n";
-
- PackageDexUsage packageDexUsage = new PackageDexUsage();
- try {
- packageDexUsage.read(new StringReader(content));
- } catch (IOException e) {
- fail();
- }
-
- // After the read we must sync the data to fill the missing information on the code paths.
- Map<String, Set<Integer>> packageToUsersMap = new HashMap<>();
- Map<String, Set<String>> packageToCodePaths = new HashMap<>();
-
- // Handle foo package.
- packageToUsersMap.put(mFooSplit2UsedByOtherApps0.mPackageName,
- new HashSet<>(Arrays.asList(mFooSplit2UsedByOtherApps0.mOwnerUserId)));
- packageToCodePaths.put(mFooSplit2UsedByOtherApps0.mPackageName,
- new HashSet<>(Arrays.asList(mFooSplit2UsedByOtherApps0.mDexFile,
- mFooSplit1User0.mDexFile, mFooBaseUser0.mDexFile)));
- // Handle bar package.
- packageToUsersMap.put(mBarBaseUser0.mPackageName,
- new HashSet<>(Arrays.asList(mBarBaseUser0.mOwnerUserId)));
- packageToCodePaths.put(mBarBaseUser0.mPackageName,
- new HashSet<>(Arrays.asList(mBarBaseUser0.mDexFile)));
-
- // Sync the data.
- packageDexUsage.syncData(packageToUsersMap, packageToCodePaths);
-
- // Update the class loaders to unknown before asserting if needed. Before version 2 we
- // didn't have any.
- String unknown = PackageDexUsage.UNKNOWN_CLASS_LOADER_CONTEXT;
- TestData fooBaseUser0 = mFooBaseUser0.updateClassLoaderContext(unknown);
- TestData fooSplit1User0 = mFooSplit1User0.updateClassLoaderContext(unknown);
- TestData fooSplit2UsedByOtherApps0 =
- mFooSplit2UsedByOtherApps0.updateClassLoaderContext(unknown);
- TestData fooSecondary1User0 = mFooSecondary1User0.updateClassLoaderContext(unknown);
- TestData fooSecondary2UsedByOtherApps0 =
- mFooSecondary2UsedByOtherApps0.updateClassLoaderContext(unknown);
- TestData barBaseUser0 = mBarBaseUser0.updateClassLoaderContext(unknown);
- TestData barSecondary1User0 = mBarSecondary1User0.updateClassLoaderContext(unknown);
-
- // Assert foo code paths. Note that we ignore the users during upgrade.
- final Set<String> ignoredUsers = null;
- assertPackageDexUsage(packageDexUsage, ignoredUsers,
- fooSplit2UsedByOtherApps0, fooSecondary1User0, fooSecondary2UsedByOtherApps0);
- // Because fooSplit2UsedByOtherApps0 is used by others, all the other code paths must
- // share the same data.
- assertPackageDexUsage(packageDexUsage, ignoredUsers,
- fooSplit1User0.updateUseByOthers(true),
- fooSecondary1User0, fooSecondary2UsedByOtherApps0);
- assertPackageDexUsage(packageDexUsage, ignoredUsers, fooBaseUser0.updateUseByOthers(true),
- fooSecondary1User0, fooSecondary2UsedByOtherApps0);
-
- // Assert bar code paths. Note that we ignore the users during upgrade.
- assertPackageDexUsage(packageDexUsage, ignoredUsers, barBaseUser0, barSecondary1User0);
- }
-
private void assertPackageDexUsage(TestData primary, TestData... secondaries) {
assertPackageDexUsage(mPackageDexUsage, null, primary, secondaries);
}