Merge "In place split install native support" into pi-dev
diff --git a/dalvik/src/main/java/dalvik/system/BaseDexClassLoader.java b/dalvik/src/main/java/dalvik/system/BaseDexClassLoader.java
index 9ce4d37..5ec115a 100644
--- a/dalvik/src/main/java/dalvik/system/BaseDexClassLoader.java
+++ b/dalvik/src/main/java/dalvik/system/BaseDexClassLoader.java
@@ -20,6 +20,7 @@
import java.net.URL;
import java.nio.ByteBuffer;
import java.util.ArrayList;
+import java.util.Collection;
import java.util.Enumeration;
import java.util.List;
@@ -139,6 +140,15 @@
pathList.addDexPath(dexPath, null /*optimizedDirectory*/);
}
+ /**
+ * Adds additional native paths for consideration in subsequent calls to
+ * {@link #findLibrary(String)}
+ * @hide
+ */
+ public void addNativePath(Collection<String> libPaths) {
+ pathList.addNativePath(libPaths);
+ }
+
@Override
protected URL findResource(String name) {
return pathList.findResource(name);
diff --git a/dalvik/src/main/java/dalvik/system/DexPathList.java b/dalvik/src/main/java/dalvik/system/DexPathList.java
index 5bd7f1c..d8f7e48 100644
--- a/dalvik/src/main/java/dalvik/system/DexPathList.java
+++ b/dalvik/src/main/java/dalvik/system/DexPathList.java
@@ -25,10 +25,12 @@
import java.nio.ByteBuffer;
import java.util.ArrayList;
import java.util.Arrays;
+import java.util.Collection;
import java.util.Collections;
import java.util.Enumeration;
import java.util.HashSet;
import java.util.List;
+import java.util.Objects;
import java.util.Set;
import libcore.io.ClassPathURLStreamHandler;
import libcore.io.IoUtils;
@@ -65,7 +67,8 @@
private Element[] dexElements;
/** List of native library path elements. */
- private final NativeLibraryElement[] nativeLibraryPathElements;
+ // Some applications rely on this field being an array or we'd use a final list here
+ /* package visible for testing */ NativeLibraryElement[] nativeLibraryPathElements;
/** List of application native library directories. */
private final List<File> nativeLibraryDirectories;
@@ -619,6 +622,33 @@
}
/**
+ * Adds a collection of library paths from which to load native libraries. Paths can be absolute
+ * native library directories (i.e. /data/app/foo/lib/arm64) or apk references (i.e.
+ * /data/app/foo/base.apk!/lib/arm64).
+ *
+ * Note: This method will attempt to dedupe elements.
+ * Note: This method replaces the value of {@link #nativeLibraryPathElements}
+ */
+ public void addNativePath(Collection<String> libPaths) {
+ if (libPaths.isEmpty()) {
+ return;
+ }
+ List<File> libFiles = new ArrayList<>(libPaths.size());
+ for (String path : libPaths) {
+ libFiles.add(new File(path));
+ }
+ ArrayList<NativeLibraryElement> newPaths =
+ new ArrayList<>(nativeLibraryPathElements.length + libPaths.size());
+ newPaths.addAll(Arrays.asList(nativeLibraryPathElements));
+ for (NativeLibraryElement element : makePathElements(libFiles)) {
+ if (!newPaths.contains(element)) {
+ newPaths.add(element);
+ }
+ }
+ nativeLibraryPathElements = newPaths.toArray(new NativeLibraryElement[newPaths.size()]);
+ }
+
+ /**
* Element of the dex/resource path. Note: should be called DexElement, but apps reflect on
* this.
*/
@@ -864,5 +894,19 @@
return null;
}
+
+ @Override
+ public boolean equals(Object o) {
+ if (this == o) return true;
+ if (!(o instanceof NativeLibraryElement)) return false;
+ NativeLibraryElement that = (NativeLibraryElement) o;
+ return Objects.equals(path, that.path) &&
+ Objects.equals(zipDir, that.zipDir);
+ }
+
+ @Override
+ public int hashCode() {
+ return Objects.hash(path, zipDir);
+ }
}
}
diff --git a/luni/src/test/java/libcore/dalvik/system/DexClassLoaderTest.java b/luni/src/test/java/libcore/dalvik/system/DexClassLoaderTest.java
index 995cab1..efc9c29 100644
--- a/luni/src/test/java/libcore/dalvik/system/DexClassLoaderTest.java
+++ b/luni/src/test/java/libcore/dalvik/system/DexClassLoaderTest.java
@@ -20,6 +20,8 @@
import java.io.File;
import java.io.InputStream;
import java.util.Arrays;
+import java.util.Collection;
+import java.util.Collections;
import java.util.Map;
import libcore.io.Streams;
@@ -36,12 +38,14 @@
private File dex2;
private File jar1;
private File jar2;
+ private File nativeLib1;
private Map<String, File> resourcesMap;
protected void setUp() throws Exception {
resourcesMap = ClassLoaderTestSupport.setupAndCopyResources(Arrays.asList(
- "loading-test.dex", "loading-test2.dex", "loading-test.jar", "loading-test2.jar"));
+ "loading-test.dex", "loading-test2.dex", "loading-test.jar", "loading-test2.jar",
+ "libfake.so"));
dex1 = resourcesMap.get("loading-test.dex");
assertNotNull(dex1);
@@ -51,6 +55,8 @@
assertNotNull(jar1);
jar2 = resourcesMap.get("loading-test2.jar");
assertNotNull(jar2);
+ nativeLib1 = resourcesMap.get("libfake.so");
+ assertNotNull(nativeLib1);
}
protected void tearDown() {
@@ -337,4 +343,26 @@
public void test_twoJar_diff_getResourceAsStream() throws Exception {
createLoaderAndCallMethod("test.TestMethods", "test_diff_getResourceAsStream", jar1, jar2);
}
+
+ /*
+ * Tests native modification behaviors
+ */
+
+ /**
+ * Checks that a adding a native library to an existing class loader makes it visible for
+ * subsequent calls.
+ * @throws Exception
+ */
+ public void test_oneDex_addNative_findsLibrary() throws Exception {
+ String path = nativeLib1.getParentFile().getAbsolutePath();
+ DexClassLoader classLoader = (DexClassLoader) createLoader(dex1);
+
+ assertNull("findLibrary should not find un-added path",
+ classLoader.findLibrary("fake"));
+
+ classLoader.addNativePath(Collections.singletonList(path));
+
+ assertNotNull("findLibrary should find newly added path",
+ classLoader.findLibrary("fake"));
+ }
}
diff --git a/luni/src/test/resources/dalvik/system/libfake.so b/luni/src/test/resources/dalvik/system/libfake.so
new file mode 100644
index 0000000..e69de29
--- /dev/null
+++ b/luni/src/test/resources/dalvik/system/libfake.so