1 /* 2 * Copyright (C) 2021 The Android Open Source Project 3 * 4 * Licensed under the Apache License, Version 2.0 (the "License"); 5 * you may not use this file except in compliance with the License. 6 * You may obtain a copy of the License at 7 * 8 * http://www.apache.org/licenses/LICENSE-2.0 9 * 10 * Unless required by applicable law or agreed to in writing, software 11 * distributed under the License is distributed on an "AS IS" BASIS, 12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 * See the License for the specific language governing permissions and 14 * limitations under the License. 15 */ 16 17 import dalvik.system.PathClassLoader; 18 import java.lang.reflect.Method; 19 import java.io.File; 20 import java.nio.ByteBuffer; 21 import java.util.Base64; 22 23 public class Main { check(boolean expected, boolean actual, String message)24 private static void check(boolean expected, boolean actual, String message) { 25 if (expected != actual) { 26 System.err.println( 27 "ERROR: " + message + " (expected=" + expected + ", actual=" + actual + ")"); 28 throw new Error(""); 29 } 30 } 31 singleLoader()32 private static ClassLoader singleLoader() { 33 return new PathClassLoader(DEX_EXTRA, /*parent*/null); 34 } 35 test(ClassLoader loader, boolean expectedHasVdexFile, boolean expectedBackedByOat, boolean invokeMethod)36 private static void test(ClassLoader loader, 37 boolean expectedHasVdexFile, 38 boolean expectedBackedByOat, 39 boolean invokeMethod) throws Exception { 40 // If ART created a vdex file, it must have verified all the classes. 41 // That happens if and only if we expect a vdex at the end of the test but 42 // do not expect it to have been loaded. 43 boolean expectedClassesVerified = expectedHasVdexFile && !expectedBackedByOat; 44 45 waitForVerifier(); 46 check(expectedClassesVerified, areClassesVerified(loader), "areClassesVerified"); 47 check(expectedHasVdexFile, hasVdexFile(loader), "hasVdexFile"); 48 check(expectedBackedByOat, isBackedByOatFile(loader), "isBackedByOatFile"); 49 check(expectedBackedByOat, areClassesPreverified(loader), "areClassesPreverified"); 50 51 if (invokeMethod) { 52 loader.loadClass("art.ClassB").getDeclaredMethod("printHello").invoke(null); 53 } 54 55 if (expectedBackedByOat) { 56 String filter = getCompilerFilter(loader.loadClass("art.ClassB")); 57 if (!("verify".equals(filter))) { 58 throw new Error("Expected verify, got " + filter); 59 } 60 } 61 } 62 main(String[] args)63 public static void main(String[] args) throws Exception { 64 System.loadLibrary(args[0]); 65 66 // Feature is disabled in debuggable mode because runtime threads are not 67 // allowed to load classes. 68 boolean featureEnabled = !isDebuggable(); 69 70 // SDK version not set. Background verification job should not have run 71 // and vdex should not have been created. 72 test(singleLoader(), /*hasVdex*/ false, /*backedByOat*/ false, /*invokeMethod*/ true); 73 74 // Feature only enabled for target SDK version Q and later. 75 setTargetSdkVersion(/* Q */ 29); 76 77 // SDK version directory is now set. Background verification job should have run, 78 // should have verified classes and written results to a vdex. 79 test(singleLoader(), /*hasVdex*/ featureEnabled, /*backedByOat*/ false, /*invokeMethod*/ true); 80 test(singleLoader(), /*hasVdex*/ featureEnabled, /*backedByOat*/ featureEnabled, 81 /*invokeMethod*/ true); 82 } 83 isDebuggable()84 private static native boolean isDebuggable(); setTargetSdkVersion(int version)85 private static native int setTargetSdkVersion(int version); waitForVerifier()86 private static native void waitForVerifier(); areClassesVerified(ClassLoader loader)87 private static native boolean areClassesVerified(ClassLoader loader); hasVdexFile(ClassLoader loader)88 private static native boolean hasVdexFile(ClassLoader loader); isBackedByOatFile(ClassLoader loader)89 private static native boolean isBackedByOatFile(ClassLoader loader); areClassesPreverified(ClassLoader loader)90 private static native boolean areClassesPreverified(ClassLoader loader); getCompilerFilter(Class cls)91 private static native String getCompilerFilter(Class cls); 92 93 private static final String DEX_LOCATION = System.getenv("DEX_LOCATION"); 94 private static final String DEX_EXTRA = 95 new File(DEX_LOCATION, "692-vdex-secondary-loader-ex.jar").getAbsolutePath(); 96 } 97