Add support for loading trusted dex files.

Which can use hidden APIs.

bug: 64382372
Test: m
Merged-In: If859beb46cbb8a815a7e2754f14095759a898a58
Change-Id: If859beb46cbb8a815a7e2754f14095759a898a58
(cherry picked from commit 9ea7438c957358721aa6606ca768f80a08237fe7)
diff --git a/dalvik/src/main/java/dalvik/system/BaseDexClassLoader.java b/dalvik/src/main/java/dalvik/system/BaseDexClassLoader.java
index 5ec115a..2ff1814 100644
--- a/dalvik/src/main/java/dalvik/system/BaseDexClassLoader.java
+++ b/dalvik/src/main/java/dalvik/system/BaseDexClassLoader.java
@@ -62,8 +62,16 @@
      */
     public BaseDexClassLoader(String dexPath, File optimizedDirectory,
             String librarySearchPath, ClassLoader parent) {
+        this(dexPath, optimizedDirectory, librarySearchPath, parent, false);
+    }
+
+    /**
+     * @hide
+     */
+    public BaseDexClassLoader(String dexPath, File optimizedDirectory,
+            String librarySearchPath, ClassLoader parent, boolean isTrusted) {
         super(parent);
-        this.pathList = new DexPathList(this, dexPath, librarySearchPath, null);
+        this.pathList = new DexPathList(this, dexPath, librarySearchPath, null, isTrusted);
 
         if (reporter != null) {
             reportClassLoaderChain();
@@ -137,7 +145,14 @@
      * @hide
      */
     public void addDexPath(String dexPath) {
-        pathList.addDexPath(dexPath, null /*optimizedDirectory*/);
+        addDexPath(dexPath, false /*isTrusted*/);
+    }
+
+    /**
+     * @hide
+     */
+    public void addDexPath(String dexPath, boolean isTrusted) {
+        pathList.addDexPath(dexPath, null /*optimizedDirectory*/, isTrusted);
     }
 
     /**
diff --git a/dalvik/src/main/java/dalvik/system/DexFile.java b/dalvik/src/main/java/dalvik/system/DexFile.java
index b677c2a..afedba5 100644
--- a/dalvik/src/main/java/dalvik/system/DexFile.java
+++ b/dalvik/src/main/java/dalvik/system/DexFile.java
@@ -379,6 +379,13 @@
     }
 
     /*
+     * Set the dex file as trusted: it can access hidden APIs of the platform.
+     */
+    /*package*/ void setTrusted() {
+        setTrusted(mCookie);
+    }
+
+    /*
      * Returns true if we managed to close the dex file.
      */
     private static native boolean closeDexFile(Object cookie);
@@ -387,6 +394,7 @@
             throws ClassNotFoundException, NoClassDefFoundError;
     private static native String[] getClassNameList(Object cookie);
     private static native boolean isBackedByOatFile(Object cookie);
+    private static native void setTrusted(Object cookie);
     /*
      * Open a DEX file.  The value returned is a magic VM cookie.  On
      * failure, an IOException is thrown.
diff --git a/dalvik/src/main/java/dalvik/system/DexPathList.java b/dalvik/src/main/java/dalvik/system/DexPathList.java
index c6af0b1..e68e365 100644
--- a/dalvik/src/main/java/dalvik/system/DexPathList.java
+++ b/dalvik/src/main/java/dalvik/system/DexPathList.java
@@ -129,7 +129,11 @@
      */
     public DexPathList(ClassLoader definingContext, String dexPath,
             String librarySearchPath, File optimizedDirectory) {
+        this(definingContext, dexPath, librarySearchPath, optimizedDirectory, false);
+    }
 
+    DexPathList(ClassLoader definingContext, String dexPath,
+            String librarySearchPath, File optimizedDirectory, boolean isTrusted) {
         if (definingContext == null) {
             throw new NullPointerException("definingContext == null");
         }
@@ -158,7 +162,7 @@
         ArrayList<IOException> suppressedExceptions = new ArrayList<IOException>();
         // save dexPath for BaseDexClassLoader
         this.dexElements = makeDexElements(splitDexPath(dexPath), optimizedDirectory,
-                                           suppressedExceptions, definingContext);
+                                           suppressedExceptions, definingContext, isTrusted);
 
         // Native libraries may exist in both the system and
         // application library paths, and we use this search order:
@@ -214,9 +218,13 @@
      * system directory for same
      */
     public void addDexPath(String dexPath, File optimizedDirectory) {
+      addDexPath(dexPath, optimizedDirectory, false);
+    }
+
+    public void addDexPath(String dexPath, File optimizedDirectory, boolean isTrusted) {
         final List<IOException> suppressedExceptionList = new ArrayList<IOException>();
         final Element[] newElements = makeDexElements(splitDexPath(dexPath), optimizedDirectory,
-                suppressedExceptionList, definingContext);
+                suppressedExceptionList, definingContext, isTrusted);
 
         if (newElements != null && newElements.length > 0) {
             final Element[] oldElements = dexElements;
@@ -310,6 +318,12 @@
      */
     private static Element[] makeDexElements(List<File> files, File optimizedDirectory,
             List<IOException> suppressedExceptions, ClassLoader loader) {
+        return makeDexElements(files, optimizedDirectory, suppressedExceptions, loader, false);
+    }
+
+
+    private static Element[] makeDexElements(List<File> files, File optimizedDirectory,
+            List<IOException> suppressedExceptions, ClassLoader loader, boolean isTrusted) {
       Element[] elements = new Element[files.size()];
       int elementsPos = 0;
       /*
@@ -323,10 +337,11 @@
           } else if (file.isFile()) {
               String name = file.getName();
 
+              DexFile dex = null;
               if (name.endsWith(DEX_SUFFIX)) {
                   // Raw dex file (not inside a zip/jar).
                   try {
-                      DexFile dex = loadDexFile(file, optimizedDirectory, loader, elements);
+                      dex = loadDexFile(file, optimizedDirectory, loader, elements);
                       if (dex != null) {
                           elements[elementsPos++] = new Element(dex, null);
                       }
@@ -335,7 +350,6 @@
                       suppressedExceptions.add(suppressed);
                   }
               } else {
-                  DexFile dex = null;
                   try {
                       dex = loadDexFile(file, optimizedDirectory, loader, elements);
                   } catch (IOException suppressed) {
@@ -355,6 +369,9 @@
                       elements[elementsPos++] = new Element(dex, file);
                   }
               }
+              if (dex != null && isTrusted) {
+                dex.setTrusted();
+              }
           } else {
               System.logW("ClassLoader referenced unknown path: " + file);
           }