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