Preverify InMemoryDexClassLoader-loaded classes from vdex

This patch creates a new subclass of OatFile - OatFileBackedByVdex -
which initializes OatDexClass instances using the verification info in
a vdex file created by a previous instance of the class loader.
The OatFile is not backed by an actual .oat file.

Bug: 72131483
Test: art/tools/run-libcore-tests.sh
Test: art/test.py -b -r -t 692 -t 693
Change-Id: I3fd055abe17ee9739c07f2e2f4fc2543e4ec8c9e
diff --git a/test/692-vdex-inmem-loader/src/Main.java b/test/692-vdex-inmem-loader/src/Main.java
index 75aef8b..4d21f5b 100644
--- a/test/692-vdex-inmem-loader/src/Main.java
+++ b/test/692-vdex-inmem-loader/src/Main.java
@@ -42,13 +42,18 @@
 
   private static void test(ClassLoader loader,
                            boolean expectedHasVdexFile,
+                           boolean expectedBackedByOat,
                            boolean invokeMethod) throws Exception {
     // If ART created a vdex file, it must have verified all the classes.
-    boolean expectedClassesVerified = expectedHasVdexFile;
+    // That happens if and only if we expect a vdex at the end of the test but
+    // do not expect it to have been loaded.
+    boolean expectedClassesVerified = expectedHasVdexFile && !expectedBackedByOat;
 
     waitForVerifier();
     check(expectedClassesVerified, areClassesVerified(loader), "areClassesVerified");
     check(expectedHasVdexFile, hasVdexFile(loader), "areClassesVerified");
+    check(expectedBackedByOat, isBackedByOatFile(loader), "isBackedByOatFile");
+    check(expectedBackedByOat, areClassesPreverified(loader), "areClassesPreverified");
 
     if (invokeMethod) {
       loader.loadClass("art.ClassB").getDeclaredMethod("printHello").invoke(null);
@@ -58,24 +63,47 @@
   public static void main(String[] args) throws Exception {
     System.loadLibrary(args[0]);
     ClassLoader[] loaders = null;
+
+    // Feature is disabled in debuggable mode because runtime threads are not
+    // allowed to load classes.
     boolean featureEnabled = !isDebuggable();
 
     // Data directory not set. Background verification job should not have run
     // and vdex should not have been created.
-    test(singleLoader(), /*hasVdex*/ false, /*invokeMethod*/ true);
+    test(singleLoader(), /*hasVdex*/ false, /*backedByOat*/ false, /*invokeMethod*/ true);
 
     // Set data directory for this process.
     setProcessDataDir(DEX_LOCATION);
 
     // Data directory is now set. Background verification job should have run,
     // should have verified classes and written results to a vdex.
-    test(singleLoader(), /*hasVdex*/ featureEnabled, /*invokeMethod*/ true);
+    test(singleLoader(), /*hasVdex*/ featureEnabled, /*backedByOat*/ false, /*invokeMethod*/ true);
+    test(singleLoader(), /*hasVdex*/ featureEnabled, /*backedByOat*/ true, /*invokeMethod*/ true);
 
     // Test loading the two dex files with separate class loaders.
     // Background verification task should still verify all classes.
     loaders = multiLoader();
-    test(loaders[0], /*hasVdex*/ featureEnabled, /*invokeMethod*/ false);
-    test(loaders[1], /*hasVdex*/ featureEnabled, /*invokeMethod*/ true);
+    test(loaders[0], /*hasVdex*/ featureEnabled, /*backedByOat*/ false, /*invokeMethod*/ false);
+    test(loaders[1], /*hasVdex*/ featureEnabled, /*backedByOat*/ false, /*invokeMethod*/ true);
+
+    loaders = multiLoader();
+    test(loaders[0], /*hasVdex*/ featureEnabled, /*backedByOat*/ featureEnabled,
+        /*invokeMethod*/ false);
+    test(loaders[1], /*hasVdex*/ featureEnabled, /*backedByOat*/ featureEnabled,
+        /*invokeMethod*/ true);
+
+    // Change boot classpath checksum.
+    appendToBootClassLoader(DEX_EXTRA, /*isCorePlatform*/ false);
+
+    loaders = multiLoader();
+    test(loaders[0], /*hasVdex*/ featureEnabled, /*backedByOat*/ false, /*invokeMethod*/ false);
+    test(loaders[1], /*hasVdex*/ featureEnabled, /*backedByOat*/ false, /*invokeMethod*/ true);
+
+    loaders = multiLoader();
+    test(loaders[0], /*hasVdex*/ featureEnabled, /*backedByOat*/ featureEnabled,
+        /*invokeMethod*/ false);
+    test(loaders[1], /*hasVdex*/ featureEnabled, /*backedByOat*/ featureEnabled,
+        /*invokeMethod*/ true);
   }
 
   private static native boolean isDebuggable();
@@ -83,6 +111,8 @@
   private static native void waitForVerifier();
   private static native boolean areClassesVerified(ClassLoader loader);
   private static native boolean hasVdexFile(ClassLoader loader);
+  private static native boolean isBackedByOatFile(ClassLoader loader);
+  private static native boolean areClassesPreverified(ClassLoader loader);
 
   // Defined in 674-hiddenapi.
   private static native void appendToBootClassLoader(String dexPath, boolean isCorePlatform);