Provide libraryPermittedPath to android runtime

Opening native libraries in isolated namespaces is limited to
the search-path (librarySearchPath). The libraryPermittedPath allows
to expand the list of allowed directories for isolated namespaces.

Bug: http://b/22548808
Bug: http://b/25853516
Change-Id: Id229be7760c3c47b7307452493bbb8bdf3faabb7
(cherry picked from commit a2656629522f9d79e2dca7418ab5963f50d0fda8)
diff --git a/dalvik/src/main/java/dalvik/system/BaseDexClassLoader.java b/dalvik/src/main/java/dalvik/system/BaseDexClassLoader.java
index 5ef00bf..0e112fc 100644
--- a/dalvik/src/main/java/dalvik/system/BaseDexClassLoader.java
+++ b/dalvik/src/main/java/dalvik/system/BaseDexClassLoader.java
@@ -37,15 +37,46 @@
      * defaults to {@code ":"} on Android
      * @param optimizedDirectory directory where optimized dex files
      * should be written; may be {@code null}
-     * @param libraryPath the list of directories containing native
+     * @param librarySearchPath the list of directories containing native
      * libraries, delimited by {@code File.pathSeparator}; may be
      * {@code null}
      * @param parent the parent class loader
+     *
+     * This method will be deprecated in the next release
      */
     public BaseDexClassLoader(String dexPath, File optimizedDirectory,
-            String libraryPath, ClassLoader parent) {
+            String librarySearchPath, ClassLoader parent) {
+        this(dexPath, optimizedDirectory, librarySearchPath, null, parent);
+    }
+
+    /**
+     * Constructs an instance.
+     *
+     * @param dexPath the list of jar/apk files containing classes and
+     * resources, delimited by {@code File.pathSeparator}, which
+     * defaults to {@code ":"} on Android
+     * @param optimizedDirectory directory where optimized dex files
+     * should be written; may be {@code null}
+     * @param librarySearchPath the list of directories containing native
+     * libraries, delimited by {@code File.pathSeparator}; may be
+     * {@code null}; directories in this list are used to search for
+     * a native library
+     * @param libraryPermittedPath allows opening native libraries under
+     * directories in this list. The list is delimited by
+     * {@code File.pathSeparator}. Note that the classloader
+     * is implicitly allowed to open libraries from the
+     * directories on libraryPath. Directories from this list
+     * are NOT used to search for the native library;
+     * may be {@code null}
+     * @param parent the parent class loader
+     *
+     * @hide
+     */
+    public BaseDexClassLoader(String dexPath, File optimizedDirectory,
+            String librarySearchPath, String libraryPermittedPath, ClassLoader parent) {
         super(parent);
-        this.pathList = new DexPathList(this, dexPath, libraryPath, optimizedDirectory);
+        this.pathList = new DexPathList(this, dexPath, librarySearchPath,
+                                        libraryPermittedPath, optimizedDirectory);
     }
 
     @Override
@@ -134,6 +165,13 @@
         return result.toString();
     }
 
+    /**
+     * @hide
+     */
+    public String getLibraryPermittedPath() {
+        return pathList.getLibraryPermittedPath();
+    }
+
     @Override public String toString() {
         return getClass().getName() + "[" + pathList + "]";
     }
diff --git a/dalvik/src/main/java/dalvik/system/DexClassLoader.java b/dalvik/src/main/java/dalvik/system/DexClassLoader.java
index a645f42..4bbdbd8 100644
--- a/dalvik/src/main/java/dalvik/system/DexClassLoader.java
+++ b/dalvik/src/main/java/dalvik/system/DexClassLoader.java
@@ -47,13 +47,48 @@
      *     defaults to {@code ":"} on Android
      * @param optimizedDirectory directory where optimized dex files
      *     should be written; must not be {@code null}
-     * @param libraryPath the list of directories containing native
+     * @param librarySearchPath the list of directories containing native
      *     libraries, delimited by {@code File.pathSeparator}; may be
      *     {@code null}
      * @param parent the parent class loader
+     *
+     * This method will be deprecated in the next release
      */
     public DexClassLoader(String dexPath, String optimizedDirectory,
-            String libraryPath, ClassLoader parent) {
-        super(dexPath, new File(optimizedDirectory), libraryPath, parent);
+            String librarySearchPath, ClassLoader parent) {
+        super(dexPath, new File(optimizedDirectory), librarySearchPath, null, parent);
+    }
+
+    /**
+     * Creates a {@code DexClassLoader} that finds interpreted and native
+     * code.  Interpreted classes are found in a set of DEX files contained
+     * in Jar or APK files.
+     *
+     * <p>The path lists are separated using the character specified by the
+     * {@code path.separator} system property, which defaults to {@code :}.
+     *
+     * @param dexPath the list of jar/apk files containing classes and
+     *     resources, delimited by {@code File.pathSeparator}, which
+     *     defaults to {@code ":"} on Android
+     * @param optimizedDirectory directory where optimized dex files
+     *     should be written; must not be {@code null}
+     * @param librarySearchPath the list of directories containing native
+     *     libraries, delimited by {@code File.pathSeparator}; may be
+     *     {@code null}
+     * @param libraryPermittedPath Allowing open native libraries under
+     * 		 directories in this list. The list is delimited by
+     *     {@code File.pathSeparator}. Note that the classloader
+     *     is implicitly allowed to open libraries from the
+     *     directories on librarySearchPath. Directories from this list
+     *     are NOT used to search for the native library;
+     *     may be {@code null}
+     * @param parent the parent class loader
+     *
+     * @hide
+     */
+    public DexClassLoader(String dexPath, String optimizedDirectory,
+            String librarySearchPath, String libraryPermittedPath, ClassLoader parent) {
+        super(dexPath, new File(optimizedDirectory), librarySearchPath,
+              libraryPermittedPath, parent);
     }
 }
diff --git a/dalvik/src/main/java/dalvik/system/DexPathList.java b/dalvik/src/main/java/dalvik/system/DexPathList.java
index d4f80e9..e9a73de 100644
--- a/dalvik/src/main/java/dalvik/system/DexPathList.java
+++ b/dalvik/src/main/java/dalvik/system/DexPathList.java
@@ -70,6 +70,9 @@
     /** List of system native library directories. */
     private final List<File> systemNativeLibraryDirectories;
 
+    /** The permitted library path for classloader-namespaces */
+    private final String libraryPermittedPath;
+
     /**
      * Exceptions thrown during creation of the dexElements list.
      */
@@ -82,14 +85,19 @@
      * classes should be defined
      * @param dexPath list of dex/resource path elements, separated by
      * {@code File.pathSeparator}
-     * @param libraryPath list of native library directory path elements,
+     * @param librarySearchPath list of native library directory path elements,
      * separated by {@code File.pathSeparator}
+     * @param libraryPermittedPath is path containing permitted directories for
+     * linker isolated namespaces (in addition to librarySearchPath which is allowed
+     * implicitly). Note that this path does not affect the search order for the library
+     * and intended for white-listing additional paths when loading native libraries
+     * by absolute path.
      * @param optimizedDirectory directory where optimized {@code .dex} files
      * should be found and written to, or {@code null} to use the default
      * system directory for same
      */
     public DexPathList(ClassLoader definingContext, String dexPath,
-            String libraryPath, File optimizedDirectory) {
+            String librarySearchPath, String libraryPermittedPath, File optimizedDirectory) {
 
         if (definingContext == null) {
             throw new NullPointerException("definingContext == null");
@@ -124,14 +132,14 @@
         // Native libraries may exist in both the system and
         // application library paths, and we use this search order:
         //
-        //   1. This class loader's library path for application libraries (libraryPath):
+        //   1. This class loader's library path for application libraries (librarySearchPath):
         //   1.1. Native library directories
         //   1.2. Path to libraries in apk-files
         //   2. The VM's library path from the system property for system libraries
         //      also known as java.library.path
         //
         // This order was reversed prior to Gingerbread; see http://b/2933456.
-        this.nativeLibraryDirectories = splitPaths(libraryPath, false);
+        this.nativeLibraryDirectories = splitPaths(librarySearchPath, false);
         this.systemNativeLibraryDirectories =
                 splitPaths(System.getProperty("java.library.path"), true);
         List<File> allNativeLibraryDirectories = new ArrayList<>(nativeLibraryDirectories);
@@ -147,6 +155,8 @@
         } else {
             dexElementsSuppressedExceptions = null;
         }
+
+        this.libraryPermittedPath = libraryPermittedPath;
     }
 
     @Override public String toString() {
@@ -169,6 +179,13 @@
     }
 
     /**
+     * For BaseDexClassLoader.getLibraryPermittedPath.
+     */
+    public String getLibraryPermittedPath() {
+        return libraryPermittedPath;
+    }
+
+    /**
      * Splits the given dex path string into elements using the path
      * separator, pruning out any elements that do not refer to existing
      * and readable files.
diff --git a/dalvik/src/main/java/dalvik/system/PathClassLoader.java b/dalvik/src/main/java/dalvik/system/PathClassLoader.java
index 32c5586..83b4366 100644
--- a/dalvik/src/main/java/dalvik/system/PathClassLoader.java
+++ b/dalvik/src/main/java/dalvik/system/PathClassLoader.java
@@ -35,7 +35,7 @@
      * @param parent the parent class loader
      */
     public PathClassLoader(String dexPath, ClassLoader parent) {
-        super(dexPath, null, null, parent);
+        super(dexPath, null, null, null, parent);
     }
 
     /**
@@ -55,13 +55,48 @@
      * @param dexPath the list of jar/apk files containing classes and
      * resources, delimited by {@code File.pathSeparator}, which
      * defaults to {@code ":"} on Android
-     * @param libraryPath the list of directories containing native
+     * @param librarySearchPath the list of directories containing native
      * libraries, delimited by {@code File.pathSeparator}; may be
      * {@code null}
      * @param parent the parent class loader
+     *
+     * This method will be deprecated in the next release
      */
-    public PathClassLoader(String dexPath, String libraryPath,
+    public PathClassLoader(String dexPath, String librarySearchPath, ClassLoader parent) {
+        super(dexPath, null, librarySearchPath, null, parent);
+    }
+
+    /**
+     * Creates a {@code PathClassLoader} that operates on two given
+     * lists of files and directories. The entries of the first list
+     * should be one of the following:
+     *
+     * <ul>
+     * <li>JAR/ZIP/APK files, possibly containing a "classes.dex" file as
+     * well as arbitrary resources.
+     * <li>Raw ".dex" files (not inside a zip file).
+     * </ul>
+     *
+     * The entries of the second list should be directories containing
+     * native library files.
+     *
+     * @param dexPath the list of jar/apk files containing classes and
+     * resources, delimited by {@code File.pathSeparator}, which
+     * defaults to {@code ":"} on Android
+     * @param librarySearchPath the list of directories containing native
+     * libraries, delimited by {@code File.pathSeparator}; may be
+     * {@code null}
+     * @param libraryPermittedPath allowing to open native libraries under
+     * directories in this list. The list is delimited by {@code File.pathSeparator}.
+     * Note that the classloader is implicitly allowed to open libraries from the
+     * directories on librarySearchPath. Directories from this list are NOT used
+     * to search for the native library; may be {@code null}
+     * @param parent the parent class loader
+     *
+     * @hide
+     */
+    public PathClassLoader(String dexPath, String librarySearchPath, String libraryPermittedPath,
             ClassLoader parent) {
-        super(dexPath, null, libraryPath, parent);
+        super(dexPath, null, librarySearchPath, libraryPermittedPath, parent);
     }
 }