Start using shared libraries class loader.
Change 1/2. Change 2/2 will setup the class loader namespace for
shared libraries.
This change sets up shared libraries class loaders for applications
and for dexopt.
bug: 111174995
Test: DexoptUtilsTest, device boots
Exempt-From-Owner-Approval: PS1 was approved by owner, PS2 is a build fix.
(cherry picked from commit 8d144eb8bd3487a68c3a0cf58d9744e7d9e1d78b)
Merged-In: Ie9a2b4eaa85cda59951703433f7a2d03bc12095d
Change-Id: I76383308418485ad6739f8a404d02c2771e4afe4
diff --git a/services/backup/java/com/android/server/backup/BackupManagerService.java b/services/backup/java/com/android/server/backup/BackupManagerService.java
index bd51af2..af3bd6d 100644
--- a/services/backup/java/com/android/server/backup/BackupManagerService.java
+++ b/services/backup/java/com/android/server/backup/BackupManagerService.java
@@ -1418,6 +1418,7 @@
app = mPackageManager.getApplicationInfo(pkg.packageName,
PackageManager.GET_SHARED_LIBRARY_FILES);
pkg.applicationInfo.sharedLibraryFiles = app.sharedLibraryFiles;
+ pkg.applicationInfo.sharedLibraryInfos = app.sharedLibraryInfos;
}
} catch (NameNotFoundException e) {
packages.remove(a);
diff --git a/services/core/java/com/android/server/pm/OtaDexoptService.java b/services/core/java/com/android/server/pm/OtaDexoptService.java
index dea7863..41eaa24 100644
--- a/services/core/java/com/android/server/pm/OtaDexoptService.java
+++ b/services/core/java/com/android/server/pm/OtaDexoptService.java
@@ -333,9 +333,7 @@
PackageDexOptimizer optimizer = new OTADexoptPackageDexOptimizer(
collectingInstaller, mPackageManagerService.mInstallLock, mContext);
- String[] libraryDependencies = pkg.usesLibraryFiles;
-
- optimizer.performDexOpt(pkg, libraryDependencies,
+ optimizer.performDexOpt(pkg, pkg.usesLibraryInfos,
null /* ISAs */,
null /* CompilerStats.PackageStats */,
mPackageManagerService.getDexManager().getPackageUseInfoOrDefault(pkg.packageName),
diff --git a/services/core/java/com/android/server/pm/PackageDexOptimizer.java b/services/core/java/com/android/server/pm/PackageDexOptimizer.java
index dc5213f..c197d23 100644
--- a/services/core/java/com/android/server/pm/PackageDexOptimizer.java
+++ b/services/core/java/com/android/server/pm/PackageDexOptimizer.java
@@ -20,6 +20,7 @@
import android.content.Context;
import android.content.pm.ApplicationInfo;
import android.content.pm.PackageParser;
+import android.content.pm.SharedLibraryInfo;
import android.content.pm.dex.ArtManager;
import android.content.pm.dex.DexMetadataHelper;
import android.os.FileUtils;
@@ -128,7 +129,7 @@
* <p>Calls to {@link com.android.server.pm.Installer#dexopt} on {@link #mInstaller} are
* synchronized on {@link #mInstallLock}.
*/
- int performDexOpt(PackageParser.Package pkg, String[] sharedLibraries,
+ int performDexOpt(PackageParser.Package pkg, List<SharedLibraryInfo> sharedLibraries,
String[] instructionSets, CompilerStats.PackageStats packageStats,
PackageDexUsage.PackageUseInfo packageUseInfo, DexoptOptions options) {
if (pkg.applicationInfo.uid == -1) {
@@ -154,7 +155,8 @@
* It assumes the install lock is held.
*/
@GuardedBy("mInstallLock")
- private int performDexOptLI(PackageParser.Package pkg, String[] sharedLibraries,
+ private int performDexOptLI(PackageParser.Package pkg,
+ List<SharedLibraryInfo> sharedLibraries,
String[] targetInstructionSets, CompilerStats.PackageStats packageStats,
PackageDexUsage.PackageUseInfo packageUseInfo, DexoptOptions options) {
final String[] instructionSets = targetInstructionSets != null ?
diff --git a/services/core/java/com/android/server/pm/PackageManagerService.java b/services/core/java/com/android/server/pm/PackageManagerService.java
index 2a605f5..47723da 100644
--- a/services/core/java/com/android/server/pm/PackageManagerService.java
+++ b/services/core/java/com/android/server/pm/PackageManagerService.java
@@ -2521,7 +2521,7 @@
for (int i = 0; i < builtInLibCount; i++) {
String name = libConfig.keyAt(i);
String path = libConfig.valueAt(i);
- addSharedLibraryLPw(path, null, name, SharedLibraryInfo.VERSION_UNDEFINED,
+ addSharedLibraryLPw(path, null, null, name, SharedLibraryInfo.VERSION_UNDEFINED,
SharedLibraryInfo.TYPE_BUILTIN, PLATFORM_PACKAGE_NAME, 0);
}
// Builtin libraries cannot encode their dependency where they are
@@ -5086,7 +5086,8 @@
}
SharedLibraryInfo resLibInfo = new SharedLibraryInfo(libInfo.getPath(),
- libInfo.getPackageName(), libInfo.getName(), libInfo.getLongVersion(),
+ libInfo.getPackageName(), libInfo.getAllCodePaths(),
+ libInfo.getName(), libInfo.getLongVersion(),
libInfo.getType(), libInfo.getDeclaringPackage(),
getPackagesUsingSharedLibraryLPr(libInfo, flags, userId),
(libInfo.getDependencies() == null
@@ -9386,7 +9387,7 @@
mDexManager.getPackageUseInfoOrDefault(depPackage.packageName), libraryOptions);
}
}
- return pdo.performDexOpt(p, p.usesLibraryFiles, instructionSets,
+ return pdo.performDexOpt(p, p.usesLibraryInfos, instructionSets,
getOrCreateCompilerPackageStats(p),
mDexManager.getPackageUseInfoOrDefault(p.packageName), options);
}
@@ -9756,7 +9757,6 @@
@GuardedBy("mPackages")
private void addSharedLibraryLPr(PackageParser.Package pkg, Set<String> usesLibraryFiles,
SharedLibraryInfo libInfo, PackageParser.Package changingLib) {
-
if (libInfo.getPath() != null) {
usesLibraryFiles.add(libInfo.getPath());
return;
@@ -11324,8 +11324,9 @@
}
}
- private boolean addSharedLibraryLPw(String path, String apk, String name, long version,
- int type, String declaringPackageName, long declaringVersionCode) {
+ private boolean addSharedLibraryLPw(String path, String apk, List<String> codePaths,
+ String name, long version, int type, String declaringPackageName,
+ long declaringVersionCode) {
LongSparseArray<SharedLibraryInfo> versionedLib = mSharedLibraries.get(name);
if (versionedLib == null) {
versionedLib = new LongSparseArray<>();
@@ -11336,7 +11337,7 @@
} else if (versionedLib.indexOfKey(version) >= 0) {
return false;
}
- SharedLibraryInfo libraryInfo = new SharedLibraryInfo(path, apk, name,
+ SharedLibraryInfo libraryInfo = new SharedLibraryInfo(path, apk, codePaths, name,
version, type, new VersionedPackage(declaringPackageName, declaringVersionCode),
null, null);
versionedLib.put(version, libraryInfo);
@@ -11423,10 +11424,17 @@
if (pkg.staticSharedLibName != null) {
// Static shared libs don't allow renaming as they have synthetic package
// names to allow install of multiple versions, so use name from manifest.
- if (addSharedLibraryLPw(null, pkg.packageName, pkg.staticSharedLibName,
+ if (addSharedLibraryLPw(null, pkg.packageName, pkg.getAllCodePaths(),
+ pkg.staticSharedLibName,
pkg.staticSharedLibVersion, SharedLibraryInfo.TYPE_STATIC,
pkg.manifestPackageName, pkg.getLongVersionCode())) {
hasStaticSharedLibs = true;
+ // Shared libraries for the package need to be updated.
+ try {
+ updateSharedLibrariesLPr(pkg, null);
+ } catch (PackageManagerException e) {
+ Slog.e(TAG, "updateSharedLibrariesLPr failed: ", e);
+ }
} else {
Slog.w(TAG, "Package " + pkg.packageName + " library "
+ pkg.staticSharedLibName + " already exists; skipping");
@@ -11468,13 +11476,19 @@
allowed = true;
}
if (allowed) {
- if (!addSharedLibraryLPw(null, pkg.packageName, name,
- SharedLibraryInfo.VERSION_UNDEFINED,
+ if (!addSharedLibraryLPw(null, pkg.packageName, pkg.getAllCodePaths(),
+ name, SharedLibraryInfo.VERSION_UNDEFINED,
SharedLibraryInfo.TYPE_DYNAMIC,
pkg.packageName, pkg.getLongVersionCode())) {
Slog.w(TAG, "Package " + pkg.packageName + " library "
+ name + " already exists; skipping");
}
+ // Shared libraries for the package need to be updated.
+ try {
+ updateSharedLibrariesLPr(pkg, null);
+ } catch (PackageManagerException e) {
+ Slog.e(TAG, "updateSharedLibrariesLPr failed: ", e);
+ }
} else {
Slog.w(TAG, "Package " + pkg.packageName + " declares lib "
+ name + " that is not declared on system image; skipping");
@@ -17711,7 +17725,7 @@
REASON_INSTALL,
DexoptOptions.DEXOPT_BOOT_COMPLETE |
DexoptOptions.DEXOPT_INSTALL_WITH_DEX_METADATA_FILE);
- mPackageDexOptimizer.performDexOpt(pkg, pkg.usesLibraryFiles,
+ mPackageDexOptimizer.performDexOpt(pkg, pkg.usesLibraryInfos,
null /* instructionSets */,
getOrCreateCompilerPackageStats(pkg),
mDexManager.getPackageUseInfoOrDefault(pkg.packageName),
diff --git a/services/core/java/com/android/server/pm/dex/DexoptUtils.java b/services/core/java/com/android/server/pm/dex/DexoptUtils.java
index 9a12a2f..93ee44c 100644
--- a/services/core/java/com/android/server/pm/dex/DexoptUtils.java
+++ b/services/core/java/com/android/server/pm/dex/DexoptUtils.java
@@ -17,6 +17,7 @@
package com.android.server.pm.dex;
import android.content.pm.ApplicationInfo;
+import android.content.pm.SharedLibraryInfo;
import android.util.Slog;
import android.util.SparseArray;
@@ -29,6 +30,11 @@
public final class DexoptUtils {
private static final String TAG = "DexoptUtils";
+ // Shared libraries have more or less followed PCL behavior due to the way
+ // they were added to the classpath pre Q.
+ private static final String SHARED_LIBRARY_LOADER_TYPE =
+ ClassLoaderFactory.getPathClassLoaderName();
+
private DexoptUtils() {}
/**
@@ -62,12 +68,15 @@
* android.app.ActivityThread, boolean, ApplicationInfo, List, List)}.
*/
public static String[] getClassLoaderContexts(ApplicationInfo info,
- String[] sharedLibraries, boolean[] pathsWithCode) {
+ List<SharedLibraryInfo> sharedLibraries, boolean[] pathsWithCode) {
// The base class loader context contains only the shared library.
- String sharedLibrariesClassPath = encodeClasspath(sharedLibraries);
- String baseApkContextClassLoader = encodeClassLoader(
- sharedLibrariesClassPath, info.classLoaderName);
+ String sharedLibrariesContext = "";
+ if (sharedLibraries != null) {
+ sharedLibrariesContext = encodeSharedLibraries(sharedLibraries);
+ }
+ String baseApkContextClassLoader = encodeClassLoader(
+ "", info.classLoaderName, sharedLibrariesContext);
if (info.getSplitCodePaths() == null) {
// The application has no splits.
return new String[] {baseApkContextClassLoader};
@@ -81,11 +90,10 @@
// The splits have an implicit dependency on the base apk.
// This means that we have to add the base apk file in addition to the shared libraries.
String baseApkName = new File(info.getBaseCodePath()).getName();
- String sharedLibrariesAndBaseClassPath =
- encodeClasspath(sharedLibrariesClassPath, baseApkName);
+ String baseClassPath = baseApkName;
// The result is stored in classLoaderContexts.
- // Index 0 is the class loaded context for the base apk.
+ // Index 0 is the class loader context for the base apk.
// Index `i` is the class loader context encoding for split `i`.
String[] classLoaderContexts = new String[/*base apk*/ 1 + splitRelativeCodePaths.length];
classLoaderContexts[0] = pathsWithCode[0] ? baseApkContextClassLoader : null;
@@ -94,10 +102,14 @@
// If the app didn't request for the splits to be loaded in isolation or if it does not
// declare inter-split dependencies, then all the splits will be loaded in the base
// apk class loader (in the order of their definition).
- String classpath = sharedLibrariesAndBaseClassPath;
+ String classpath = baseClassPath;
for (int i = 1; i < classLoaderContexts.length; i++) {
- classLoaderContexts[i] = pathsWithCode[i]
- ? encodeClassLoader(classpath, info.classLoaderName) : null;
+ if (pathsWithCode[i]) {
+ classLoaderContexts[i] = encodeClassLoader(
+ classpath, info.classLoaderName, sharedLibrariesContext);
+ } else {
+ classLoaderContexts[i] = null;
+ }
// Note that the splits with no code are not removed from the classpath computation.
// i.e. split_n might get the split_n-1 in its classpath dependency even
// if split_n-1 has no code.
@@ -124,7 +136,7 @@
info.splitClassLoaderNames[i]);
}
String splitDependencyOnBase = encodeClassLoader(
- sharedLibrariesAndBaseClassPath, info.classLoaderName);
+ baseClassPath, info.classLoaderName);
SparseArray<int[]> splitDependencies = info.splitDependencies;
// Note that not all splits have dependencies (e.g. configuration splits)
@@ -149,7 +161,8 @@
// any dependency. In this case its context equals its declared class loader.
classLoaderContexts[i] = classLoaderContexts[i] == null
? splitClassLoader
- : encodeClassLoaderChain(splitClassLoader, classLoaderContexts[i]);
+ : encodeClassLoaderChain(splitClassLoader, classLoaderContexts[i])
+ + sharedLibrariesContext;
} else {
// This is a split without code, it has no dependency and it is not compiled.
// Its context will be null.
@@ -207,6 +220,31 @@
return splitContext;
}
+ private static String encodeSharedLibrary(SharedLibraryInfo sharedLibrary) {
+ List<String> paths = sharedLibrary.getAllCodePaths();
+ String classLoaderSpec = encodeClassLoader(
+ encodeClasspath(paths.toArray(new String[paths.size()])),
+ SHARED_LIBRARY_LOADER_TYPE);
+ if (sharedLibrary.getDependencies() != null) {
+ classLoaderSpec += encodeSharedLibraries(sharedLibrary.getDependencies());
+ }
+ return classLoaderSpec;
+ }
+
+ private static String encodeSharedLibraries(List<SharedLibraryInfo> sharedLibraries) {
+ String sharedLibrariesContext = "{";
+ boolean first = true;
+ for (SharedLibraryInfo info : sharedLibraries) {
+ if (!first) {
+ sharedLibrariesContext += "#";
+ }
+ first = false;
+ sharedLibrariesContext += encodeSharedLibrary(info);
+ }
+ sharedLibrariesContext += "}";
+ return sharedLibrariesContext;
+ }
+
/**
* Encodes the shared libraries classpathElements in a format accepted by dexopt.
* NOTE: Keep this in sync with the dexopt expectations! Right now that is
@@ -258,6 +296,14 @@
}
/**
+ * Same as above, but appends {@param sharedLibraries} to the result.
+ */
+ private static String encodeClassLoader(String classpath, String classLoaderName,
+ String sharedLibraries) {
+ return encodeClassLoader(classpath, classLoaderName) + sharedLibraries;
+ }
+
+ /**
* Links to dependencies together in a format accepted by dexopt.
* For the special case when either of cl1 or cl2 equals
* {@link PackageDexOptimizer#SKIP_SHARED_LIBRARY_CHECK}, the method returns the same. This
diff --git a/services/tests/servicestests/src/com/android/server/pm/PackageParserTest.java b/services/tests/servicestests/src/com/android/server/pm/PackageParserTest.java
index cdbc665..69c0c0f 100644
--- a/services/tests/servicestests/src/com/android/server/pm/PackageParserTest.java
+++ b/services/tests/servicestests/src/com/android/server/pm/PackageParserTest.java
@@ -489,7 +489,8 @@
pkg.usesLibraryFiles = new String[] { "foo13"};
pkg.usesLibraryInfos = new ArrayList<>();
- pkg.usesLibraryInfos.add(new SharedLibraryInfo(null, null, null, 0L, 0, null, null, null));
+ pkg.usesLibraryInfos.add(
+ new SharedLibraryInfo(null, null, null, null, 0L, 0, null, null, null));
pkg.mOriginalPackages = new ArrayList<>();
pkg.mOriginalPackages.add("foo14");
diff --git a/services/tests/servicestests/src/com/android/server/pm/dex/DexoptUtilsTest.java b/services/tests/servicestests/src/com/android/server/pm/dex/DexoptUtilsTest.java
index 6e0f56c..1542120 100644
--- a/services/tests/servicestests/src/com/android/server/pm/dex/DexoptUtilsTest.java
+++ b/services/tests/servicestests/src/com/android/server/pm/dex/DexoptUtilsTest.java
@@ -28,6 +28,7 @@
import android.content.pm.ApplicationInfo;
import android.support.test.filters.SmallTest;
import android.support.test.runner.AndroidJUnit4;
+import android.content.pm.SharedLibraryInfo;
import android.util.SparseArray;
import dalvik.system.DelegateLastClassLoader;
@@ -39,6 +40,7 @@
import java.io.File;
import java.util.Arrays;
+import java.util.ArrayList;
import java.util.Collections;
import java.util.List;
@@ -108,22 +110,31 @@
return data;
}
+ private List<SharedLibraryInfo> createMockSharedLibrary(String [] sharedLibrary) {
+ SharedLibraryInfo info = new SharedLibraryInfo(null, null, Arrays.asList(sharedLibrary),
+ null, 0L, SharedLibraryInfo.TYPE_STATIC, null, null, null);
+ ArrayList<SharedLibraryInfo> libraries = new ArrayList<>();
+ libraries.add(info);
+ return libraries;
+ }
+
@Test
public void testSplitChain() {
TestData data = createMockApplicationInfo(PATH_CLASS_LOADER_NAME, true, true);
- String[] sharedLibrary = new String[] {"a.dex", "b.dex"};
+ List<SharedLibraryInfo> sharedLibrary =
+ createMockSharedLibrary(new String[] {"a.dex", "b.dex"});
String[] contexts = DexoptUtils.getClassLoaderContexts(
data.info, sharedLibrary, data.pathsWithCode);
assertEquals(9, contexts.length);
- assertEquals("PCL[a.dex:b.dex]", contexts[0]);
- assertEquals("DLC[];DLC[base-2.dex];PCL[base-4.dex];PCL[a.dex:b.dex:base.dex]",
+ assertEquals("PCL[]{PCL[a.dex:b.dex]}", contexts[0]);
+ assertEquals("DLC[];DLC[base-2.dex];PCL[base-4.dex];PCL[base.dex]{PCL[a.dex:b.dex]}",
contexts[1]);
- assertEquals("DLC[];PCL[base-4.dex];PCL[a.dex:b.dex:base.dex]", contexts[2]);
- assertEquals("PCL[];PCL[base-4.dex];PCL[a.dex:b.dex:base.dex]", contexts[3]);
- assertEquals("PCL[];PCL[a.dex:b.dex:base.dex]", contexts[4]);
- assertEquals("PCL[];PCL[a.dex:b.dex:base.dex]", contexts[5]);
- assertEquals("PCL[];PCL[base-5.dex];PCL[a.dex:b.dex:base.dex]", contexts[6]);
+ assertEquals("DLC[];PCL[base-4.dex];PCL[base.dex]{PCL[a.dex:b.dex]}", contexts[2]);
+ assertEquals("PCL[];PCL[base-4.dex];PCL[base.dex]{PCL[a.dex:b.dex]}", contexts[3]);
+ assertEquals("PCL[];PCL[base.dex]{PCL[a.dex:b.dex]}", contexts[4]);
+ assertEquals("PCL[];PCL[base.dex]{PCL[a.dex:b.dex]}", contexts[5]);
+ assertEquals("PCL[];PCL[base-5.dex];PCL[base.dex]{PCL[a.dex:b.dex]}", contexts[6]);
assertEquals(null, contexts[7]); // config split
assertEquals("PCL[]", contexts[8]); // feature split with no dependency
}
@@ -131,25 +142,28 @@
@Test
public void testSplitChainNoSplitDependencies() {
TestData data = createMockApplicationInfo(PATH_CLASS_LOADER_NAME, true, false);
- String[] sharedLibrary = new String[] {"a.dex", "b.dex"};
+ List<SharedLibraryInfo> sharedLibrary =
+ createMockSharedLibrary(new String[] {"a.dex", "b.dex"});
String[] contexts = DexoptUtils.getClassLoaderContexts(
data.info, sharedLibrary, data.pathsWithCode);
assertEquals(9, contexts.length);
- assertEquals("PCL[a.dex:b.dex]", contexts[0]);
- assertEquals("PCL[a.dex:b.dex:base.dex]", contexts[1]);
- assertEquals("PCL[a.dex:b.dex:base.dex:base-1.dex]", contexts[2]);
- assertEquals("PCL[a.dex:b.dex:base.dex:base-1.dex:base-2.dex]", contexts[3]);
- assertEquals("PCL[a.dex:b.dex:base.dex:base-1.dex:base-2.dex:base-3.dex]", contexts[4]);
+ assertEquals("PCL[]{PCL[a.dex:b.dex]}", contexts[0]);
+ assertEquals("PCL[base.dex]{PCL[a.dex:b.dex]}", contexts[1]);
+ assertEquals("PCL[base.dex:base-1.dex]{PCL[a.dex:b.dex]}", contexts[2]);
+ assertEquals("PCL[base.dex:base-1.dex:base-2.dex]{PCL[a.dex:b.dex]}", contexts[3]);
assertEquals(
- "PCL[a.dex:b.dex:base.dex:base-1.dex:base-2.dex:base-3.dex:base-4.dex]",
+ "PCL[base.dex:base-1.dex:base-2.dex:base-3.dex]{PCL[a.dex:b.dex]}",
+ contexts[4]);
+ assertEquals(
+ "PCL[base.dex:base-1.dex:base-2.dex:base-3.dex:base-4.dex]{PCL[a.dex:b.dex]}",
contexts[5]);
assertEquals(
- "PCL[a.dex:b.dex:base.dex:base-1.dex:base-2.dex:base-3.dex:base-4.dex:base-5.dex]",
+ "PCL[base.dex:base-1.dex:base-2.dex:base-3.dex:base-4.dex:base-5.dex]{PCL[a.dex:b.dex]}",
contexts[6]);
assertEquals(null, contexts[7]); // config split
assertEquals(
- "PCL[a.dex:b.dex:base.dex:base-1.dex:base-2.dex:base-3.dex:base-4.dex:base-5.dex:base-6.dex:config-split-7.dex]",
+ "PCL[base.dex:base-1.dex:base-2.dex:base-3.dex:base-4.dex:base-5.dex:base-6.dex:config-split-7.dex]{PCL[a.dex:b.dex]}",
contexts[8]); // feature split with no dependency
}
@@ -200,18 +214,21 @@
public void testSplitChainWithNullPrimaryClassLoader() {
// A null classLoaderName should mean PathClassLoader.
TestData data = createMockApplicationInfo(null, true, true);
- String[] sharedLibrary = new String[] {"a.dex", "b.dex"};
+ List<SharedLibraryInfo> sharedLibrary =
+ createMockSharedLibrary(new String[] {"a.dex", "b.dex"});
String[] contexts = DexoptUtils.getClassLoaderContexts(
data.info, sharedLibrary, data.pathsWithCode);
assertEquals(9, contexts.length);
- assertEquals("PCL[a.dex:b.dex]", contexts[0]);
- assertEquals("DLC[];DLC[base-2.dex];PCL[base-4.dex];PCL[a.dex:b.dex:base.dex]", contexts[1]);
- assertEquals("DLC[];PCL[base-4.dex];PCL[a.dex:b.dex:base.dex]", contexts[2]);
- assertEquals("PCL[];PCL[base-4.dex];PCL[a.dex:b.dex:base.dex]", contexts[3]);
- assertEquals("PCL[];PCL[a.dex:b.dex:base.dex]", contexts[4]);
- assertEquals("PCL[];PCL[a.dex:b.dex:base.dex]", contexts[5]);
- assertEquals("PCL[];PCL[base-5.dex];PCL[a.dex:b.dex:base.dex]", contexts[6]);
+ assertEquals("PCL[]{PCL[a.dex:b.dex]}", contexts[0]);
+ assertEquals(
+ "DLC[];DLC[base-2.dex];PCL[base-4.dex];PCL[base.dex]{PCL[a.dex:b.dex]}",
+ contexts[1]);
+ assertEquals("DLC[];PCL[base-4.dex];PCL[base.dex]{PCL[a.dex:b.dex]}", contexts[2]);
+ assertEquals("PCL[];PCL[base-4.dex];PCL[base.dex]{PCL[a.dex:b.dex]}", contexts[3]);
+ assertEquals("PCL[];PCL[base.dex]{PCL[a.dex:b.dex]}", contexts[4]);
+ assertEquals("PCL[];PCL[base.dex]{PCL[a.dex:b.dex]}", contexts[5]);
+ assertEquals("PCL[];PCL[base-5.dex];PCL[base.dex]{PCL[a.dex:b.dex]}", contexts[6]);
assertEquals(null, contexts[7]); // config split
assertEquals("PCL[]", contexts[8]); // feature split with no dependency
}
@@ -219,35 +236,38 @@
@Test
public void tesNoSplits() {
TestData data = createMockApplicationInfo(PATH_CLASS_LOADER_NAME, false, false);
- String[] sharedLibrary = new String[] {"a.dex", "b.dex"};
+ List<SharedLibraryInfo> sharedLibrary =
+ createMockSharedLibrary(new String[] {"a.dex", "b.dex"});
String[] contexts = DexoptUtils.getClassLoaderContexts(
data.info, sharedLibrary, data.pathsWithCode);
assertEquals(1, contexts.length);
- assertEquals("PCL[a.dex:b.dex]", contexts[0]);
+ assertEquals("PCL[]{PCL[a.dex:b.dex]}", contexts[0]);
}
@Test
public void tesNoSplitsNullClassLoaderName() {
TestData data = createMockApplicationInfo(null, false, false);
- String[] sharedLibrary = new String[] {"a.dex", "b.dex"};
+ List<SharedLibraryInfo> sharedLibrary =
+ createMockSharedLibrary(new String[] {"a.dex", "b.dex"});
String[] contexts = DexoptUtils.getClassLoaderContexts(
data.info, sharedLibrary, data.pathsWithCode);
assertEquals(1, contexts.length);
- assertEquals("PCL[a.dex:b.dex]", contexts[0]);
+ assertEquals("PCL[]{PCL[a.dex:b.dex]}", contexts[0]);
}
@Test
public void tesNoSplitDelegateLast() {
TestData data = createMockApplicationInfo(
DELEGATE_LAST_CLASS_LOADER_NAME, false, false);
- String[] sharedLibrary = new String[] {"a.dex", "b.dex"};
+ List<SharedLibraryInfo> sharedLibrary =
+ createMockSharedLibrary(new String[] {"a.dex", "b.dex"});
String[] contexts = DexoptUtils.getClassLoaderContexts(
data.info, sharedLibrary, data.pathsWithCode);
assertEquals(1, contexts.length);
- assertEquals("DLC[a.dex:b.dex]", contexts[0]);
+ assertEquals("DLC[]{PCL[a.dex:b.dex]}", contexts[0]);
}
@Test
@@ -276,7 +296,8 @@
TestData data = createMockApplicationInfo(null, true, false);
Arrays.fill(data.pathsWithCode, false);
- String[] sharedLibrary = new String[] {"a.dex", "b.dex"};
+ List<SharedLibraryInfo> sharedLibrary =
+ createMockSharedLibrary(new String[] {"a.dex", "b.dex"});
String[] contexts = DexoptUtils.getClassLoaderContexts(
data.info, sharedLibrary, data.pathsWithCode);
@@ -295,18 +316,21 @@
public void testContextBaseNoCode() {
TestData data = createMockApplicationInfo(null, true, true);
data.pathsWithCode[0] = false;
- String[] sharedLibrary = new String[] {"a.dex", "b.dex"};
+ List<SharedLibraryInfo> sharedLibrary =
+ createMockSharedLibrary(new String[] {"a.dex", "b.dex"});
String[] contexts = DexoptUtils.getClassLoaderContexts(
data.info, sharedLibrary, data.pathsWithCode);
assertEquals(9, contexts.length);
assertEquals(null, contexts[0]);
- assertEquals("DLC[];DLC[base-2.dex];PCL[base-4.dex];PCL[a.dex:b.dex:base.dex]", contexts[1]);
- assertEquals("DLC[];PCL[base-4.dex];PCL[a.dex:b.dex:base.dex]", contexts[2]);
- assertEquals("PCL[];PCL[base-4.dex];PCL[a.dex:b.dex:base.dex]", contexts[3]);
- assertEquals("PCL[];PCL[a.dex:b.dex:base.dex]", contexts[4]);
- assertEquals("PCL[];PCL[a.dex:b.dex:base.dex]", contexts[5]);
- assertEquals("PCL[];PCL[base-5.dex];PCL[a.dex:b.dex:base.dex]", contexts[6]);
+ assertEquals(
+ "DLC[];DLC[base-2.dex];PCL[base-4.dex];PCL[base.dex]{PCL[a.dex:b.dex]}",
+ contexts[1]);
+ assertEquals("DLC[];PCL[base-4.dex];PCL[base.dex]{PCL[a.dex:b.dex]}", contexts[2]);
+ assertEquals("PCL[];PCL[base-4.dex];PCL[base.dex]{PCL[a.dex:b.dex]}", contexts[3]);
+ assertEquals("PCL[];PCL[base.dex]{PCL[a.dex:b.dex]}", contexts[4]);
+ assertEquals("PCL[];PCL[base.dex]{PCL[a.dex:b.dex]}", contexts[5]);
+ assertEquals("PCL[];PCL[base-5.dex];PCL[base.dex]{PCL[a.dex:b.dex]}", contexts[6]);
assertEquals(null, contexts[7]);
}