1*795d594fSAndroid Build Coastguard Worker /* 2*795d594fSAndroid Build Coastguard Worker * Copyright (C) 2019 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.InMemoryDexClassLoader; 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 } 29*795d594fSAndroid Build Coastguard Worker } 30*795d594fSAndroid Build Coastguard Worker singleLoader()31*795d594fSAndroid Build Coastguard Worker private static ClassLoader singleLoader() { 32*795d594fSAndroid Build Coastguard Worker return new InMemoryDexClassLoader( 33*795d594fSAndroid Build Coastguard Worker new ByteBuffer[] { ByteBuffer.wrap(DEX_BYTES_A), ByteBuffer.wrap(DEX_BYTES_B) }, 34*795d594fSAndroid Build Coastguard Worker /*parent*/null); 35*795d594fSAndroid Build Coastguard Worker } 36*795d594fSAndroid Build Coastguard Worker multiLoader()37*795d594fSAndroid Build Coastguard Worker private static ClassLoader[] multiLoader() { 38*795d594fSAndroid Build Coastguard Worker ClassLoader clA = new InMemoryDexClassLoader(ByteBuffer.wrap(DEX_BYTES_A), /*parent*/ null); 39*795d594fSAndroid Build Coastguard Worker ClassLoader clB = new InMemoryDexClassLoader(ByteBuffer.wrap(DEX_BYTES_B), /*parent*/ clA); 40*795d594fSAndroid Build Coastguard Worker return new ClassLoader[] { clA, clB }; 41*795d594fSAndroid Build Coastguard Worker } 42*795d594fSAndroid Build Coastguard Worker test(ClassLoader loader, boolean expectedHasVdexFile, boolean expectedBackedByOat, boolean invokeMethod)43*795d594fSAndroid Build Coastguard Worker private static void test(ClassLoader loader, 44*795d594fSAndroid Build Coastguard Worker boolean expectedHasVdexFile, 45*795d594fSAndroid Build Coastguard Worker boolean expectedBackedByOat, 46*795d594fSAndroid Build Coastguard Worker boolean invokeMethod) throws Exception { 47*795d594fSAndroid Build Coastguard Worker // If ART created a vdex file, it must have verified all the classes. 48*795d594fSAndroid Build Coastguard Worker // That happens if and only if we expect a vdex at the end of the test but 49*795d594fSAndroid Build Coastguard Worker // do not expect it to have been loaded. 50*795d594fSAndroid Build Coastguard Worker boolean expectedClassesVerified = expectedHasVdexFile && !expectedBackedByOat; 51*795d594fSAndroid Build Coastguard Worker 52*795d594fSAndroid Build Coastguard Worker waitForVerifier(); 53*795d594fSAndroid Build Coastguard Worker check(expectedClassesVerified, areClassesVerified(loader), "areClassesVerified"); 54*795d594fSAndroid Build Coastguard Worker check(expectedHasVdexFile, hasVdexFile(loader), "areClassesVerified"); 55*795d594fSAndroid Build Coastguard Worker check(expectedBackedByOat, isBackedByOatFile(loader), "isBackedByOatFile"); 56*795d594fSAndroid Build Coastguard Worker check(expectedBackedByOat, areClassesPreverified(loader), "areClassesPreverified"); 57*795d594fSAndroid Build Coastguard Worker 58*795d594fSAndroid Build Coastguard Worker if (invokeMethod) { 59*795d594fSAndroid Build Coastguard Worker loader.loadClass("art.ClassB").getDeclaredMethod("printHello").invoke(null); 60*795d594fSAndroid Build Coastguard Worker 61*795d594fSAndroid Build Coastguard Worker if (expectedBackedByOat) { 62*795d594fSAndroid Build Coastguard Worker String filter = getCompilerFilter(loader.loadClass("art.ClassB")); 63*795d594fSAndroid Build Coastguard Worker if (!("verify".equals(filter))) { 64*795d594fSAndroid Build Coastguard Worker throw new Error("Expected verify, got " + filter); 65*795d594fSAndroid Build Coastguard Worker } 66*795d594fSAndroid Build Coastguard Worker } 67*795d594fSAndroid Build Coastguard Worker } 68*795d594fSAndroid Build Coastguard Worker } 69*795d594fSAndroid Build Coastguard Worker main(String[] args)70*795d594fSAndroid Build Coastguard Worker public static void main(String[] args) throws Exception { 71*795d594fSAndroid Build Coastguard Worker System.loadLibrary(args[0]); 72*795d594fSAndroid Build Coastguard Worker ClassLoader[] loaders = null; 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 // Feature is disabled in debuggable mode because runtime threads are not 78*795d594fSAndroid Build Coastguard Worker // allowed to load classes. 79*795d594fSAndroid Build Coastguard Worker boolean featureEnabled = !isDebuggable(); 80*795d594fSAndroid Build Coastguard Worker 81*795d594fSAndroid Build Coastguard Worker // Data directory not set. Background verification job should not have run 82*795d594fSAndroid Build Coastguard Worker // and vdex should not have been created. 83*795d594fSAndroid Build Coastguard Worker test(singleLoader(), /*hasVdex*/ false, /*backedByOat*/ false, /*invokeMethod*/ true); 84*795d594fSAndroid Build Coastguard Worker 85*795d594fSAndroid Build Coastguard Worker // Set data directory for this process. 86*795d594fSAndroid Build Coastguard Worker setProcessDataDir(DEX_LOCATION); 87*795d594fSAndroid Build Coastguard Worker 88*795d594fSAndroid Build Coastguard Worker // Data directory is now set. Background verification job should have run, 89*795d594fSAndroid Build Coastguard Worker // should have verified classes and written results to a vdex. 90*795d594fSAndroid Build Coastguard Worker test(singleLoader(), /*hasVdex*/ featureEnabled, /*backedByOat*/ false, /*invokeMethod*/ true); 91*795d594fSAndroid Build Coastguard Worker test(singleLoader(), /*hasVdex*/ featureEnabled, /*backedByOat*/ featureEnabled, 92*795d594fSAndroid Build Coastguard Worker /*invokeMethod*/ true); 93*795d594fSAndroid Build Coastguard Worker 94*795d594fSAndroid Build Coastguard Worker // Test loading the two dex files with separate class loaders. 95*795d594fSAndroid Build Coastguard Worker // Background verification task should still verify all classes. 96*795d594fSAndroid Build Coastguard Worker loaders = multiLoader(); 97*795d594fSAndroid Build Coastguard Worker test(loaders[0], /*hasVdex*/ featureEnabled, /*backedByOat*/ false, /*invokeMethod*/ false); 98*795d594fSAndroid Build Coastguard Worker test(loaders[1], /*hasVdex*/ featureEnabled, /*backedByOat*/ false, /*invokeMethod*/ true); 99*795d594fSAndroid Build Coastguard Worker 100*795d594fSAndroid Build Coastguard Worker loaders = multiLoader(); 101*795d594fSAndroid Build Coastguard Worker test(loaders[0], /*hasVdex*/ featureEnabled, /*backedByOat*/ featureEnabled, 102*795d594fSAndroid Build Coastguard Worker /*invokeMethod*/ false); 103*795d594fSAndroid Build Coastguard Worker test(loaders[1], /*hasVdex*/ featureEnabled, /*backedByOat*/ featureEnabled, 104*795d594fSAndroid Build Coastguard Worker /*invokeMethod*/ true); 105*795d594fSAndroid Build Coastguard Worker 106*795d594fSAndroid Build Coastguard Worker // Change boot classpath checksum. vdex files can still be loaded. 107*795d594fSAndroid Build Coastguard Worker appendToBootClassLoader(DEX_EXTRA, /*isCorePlatform*/ false); 108*795d594fSAndroid Build Coastguard Worker 109*795d594fSAndroid Build Coastguard Worker loaders = multiLoader(); 110*795d594fSAndroid Build Coastguard Worker test(loaders[0], /*hasVdex*/ featureEnabled, /*backedByOat*/ featureEnabled, 111*795d594fSAndroid Build Coastguard Worker /*invokeMethod*/ false); 112*795d594fSAndroid Build Coastguard Worker test(loaders[1], /*hasVdex*/ featureEnabled, /*backedByOat*/ featureEnabled, 113*795d594fSAndroid Build Coastguard Worker /*invokeMethod*/ true); 114*795d594fSAndroid Build Coastguard Worker 115*795d594fSAndroid Build Coastguard Worker loaders = multiLoader(); 116*795d594fSAndroid Build Coastguard Worker test(loaders[0], /*hasVdex*/ featureEnabled, /*backedByOat*/ featureEnabled, 117*795d594fSAndroid Build Coastguard Worker /*invokeMethod*/ false); 118*795d594fSAndroid Build Coastguard Worker test(loaders[1], /*hasVdex*/ featureEnabled, /*backedByOat*/ featureEnabled, 119*795d594fSAndroid Build Coastguard Worker /*invokeMethod*/ true); 120*795d594fSAndroid Build Coastguard Worker } 121*795d594fSAndroid Build Coastguard Worker isDebuggable()122*795d594fSAndroid Build Coastguard Worker private static native boolean isDebuggable(); setTargetSdkVersion(int version)123*795d594fSAndroid Build Coastguard Worker private static native int setTargetSdkVersion(int version); setProcessDataDir(String path)124*795d594fSAndroid Build Coastguard Worker private static native void setProcessDataDir(String path); waitForVerifier()125*795d594fSAndroid Build Coastguard Worker private static native void waitForVerifier(); areClassesVerified(ClassLoader loader)126*795d594fSAndroid Build Coastguard Worker private static native boolean areClassesVerified(ClassLoader loader); hasVdexFile(ClassLoader loader)127*795d594fSAndroid Build Coastguard Worker private static native boolean hasVdexFile(ClassLoader loader); isBackedByOatFile(ClassLoader loader)128*795d594fSAndroid Build Coastguard Worker private static native boolean isBackedByOatFile(ClassLoader loader); areClassesPreverified(ClassLoader loader)129*795d594fSAndroid Build Coastguard Worker private static native boolean areClassesPreverified(ClassLoader loader); getCompilerFilter(Class cls)130*795d594fSAndroid Build Coastguard Worker private static native String getCompilerFilter(Class cls); 131*795d594fSAndroid Build Coastguard Worker 132*795d594fSAndroid Build Coastguard Worker // Defined in 674-hiddenapi. appendToBootClassLoader(String dexPath, boolean isCorePlatform)133*795d594fSAndroid Build Coastguard Worker private static native void appendToBootClassLoader(String dexPath, boolean isCorePlatform); 134*795d594fSAndroid Build Coastguard Worker 135*795d594fSAndroid Build Coastguard Worker private static final String DEX_LOCATION = System.getenv("DEX_LOCATION"); 136*795d594fSAndroid Build Coastguard Worker private static final String DEX_EXTRA = 137*795d594fSAndroid Build Coastguard Worker new File(DEX_LOCATION, "692-vdex-inmem-loader-ex.jar").getAbsolutePath(); 138*795d594fSAndroid Build Coastguard Worker 139*795d594fSAndroid Build Coastguard Worker private static final byte[] DEX_BYTES_A = Base64.getDecoder().decode( 140*795d594fSAndroid Build Coastguard Worker "ZGV4CjAzNQBxYu/tdPfiHaRPYr5yaT6ko9V/xMinr1OwAgAAcAAAAHhWNBIAAAAAAAAAABwCAAAK" + 141*795d594fSAndroid Build Coastguard Worker "AAAAcAAAAAQAAACYAAAAAgAAAKgAAAAAAAAAAAAAAAMAAADAAAAAAQAAANgAAAC4AQAA+AAAADAB" + 142*795d594fSAndroid Build Coastguard Worker "AAA4AQAARQEAAEwBAABPAQAAXQEAAHEBAACFAQAAiAEAAJIBAAAEAAAABQAAAAYAAAAHAAAAAwAA" + 143*795d594fSAndroid Build Coastguard Worker "AAIAAAAAAAAABwAAAAMAAAAAAAAAAAABAAAAAAAAAAAACAAAAAEAAQAAAAAAAAAAAAEAAAABAAAA" + 144*795d594fSAndroid Build Coastguard Worker "AAAAAAEAAAAAAAAACQIAAAAAAAABAAAAAAAAACwBAAADAAAAGgACABEAAAABAAEAAQAAACgBAAAE" + 145*795d594fSAndroid Build Coastguard Worker "AAAAcBACAAAADgATAA4AFQAOAAY8aW5pdD4AC0NsYXNzQS5qYXZhAAVIZWxsbwABTAAMTGFydC9D" + 146*795d594fSAndroid Build Coastguard Worker "bGFzc0E7ABJMamF2YS9sYW5nL09iamVjdDsAEkxqYXZhL2xhbmcvU3RyaW5nOwABVgAIZ2V0SGVs" + 147*795d594fSAndroid Build Coastguard Worker "bG8AdX5+RDh7ImNvbXBpbGF0aW9uLW1vZGUiOiJkZWJ1ZyIsIm1pbi1hcGkiOjEsInNoYS0xIjoi" + 148*795d594fSAndroid Build Coastguard Worker "OTY2MDhmZDdiYmNjZGQyMjc2Y2Y4OTI4M2QyYjgwY2JmYzRmYzgxYyIsInZlcnNpb24iOiIxLjUu" + 149*795d594fSAndroid Build Coastguard Worker "NC1kZXYifQAAAAIAAIGABJACAQn4AQAAAAAADAAAAAAAAAABAAAAAAAAAAEAAAAKAAAAcAAAAAIA" + 150*795d594fSAndroid Build Coastguard Worker "AAAEAAAAmAAAAAMAAAACAAAAqAAAAAUAAAADAAAAwAAAAAYAAAABAAAA2AAAAAEgAAACAAAA+AAA" + 151*795d594fSAndroid Build Coastguard Worker "AAMgAAACAAAAKAEAAAIgAAAKAAAAMAEAAAAgAAABAAAACQIAAAMQAAABAAAAGAIAAAAQAAABAAAA" + 152*795d594fSAndroid Build Coastguard Worker "HAIAAA=="); 153*795d594fSAndroid Build Coastguard Worker private static final byte[] DEX_BYTES_B = Base64.getDecoder().decode( 154*795d594fSAndroid Build Coastguard Worker "ZGV4CjAzNQB+hWvce73hXt7ZVNgp9RAyMLSwQzsWUjV4AwAAcAAAAHhWNBIAAAAAAAAAAMwCAAAQ" + 155*795d594fSAndroid Build Coastguard Worker "AAAAcAAAAAcAAACwAAAAAwAAAMwAAAABAAAA8AAAAAUAAAD4AAAAAQAAACABAAA4AgAAQAEAAI4B" + 156*795d594fSAndroid Build Coastguard Worker "AACWAQAAowEAAKYBAAC0AQAAwgEAANkBAADtAQAAAQIAABUCAAAYAgAAHAIAACYCAAArAgAANwIA" + 157*795d594fSAndroid Build Coastguard Worker "AEACAAADAAAABAAAAAUAAAAGAAAABwAAAAgAAAAJAAAAAgAAAAQAAAAAAAAACQAAAAYAAAAAAAAA" + 158*795d594fSAndroid Build Coastguard Worker "CgAAAAYAAACIAQAABQACAAwAAAAAAAAACwAAAAEAAQAAAAAAAQABAA0AAAACAAIADgAAAAMAAQAA" + 159*795d594fSAndroid Build Coastguard Worker "AAAAAQAAAAEAAAADAAAAAAAAAAEAAAAAAAAAtwIAAAAAAAABAAEAAQAAAHwBAAAEAAAAcBAEAAAA" + 160*795d594fSAndroid Build Coastguard Worker "DgACAAAAAgAAAIABAAAKAAAAYgAAAHEAAAAAAAwBbiADABAADgATAA4AFQAOlgAAAAABAAAABAAG" + 161*795d594fSAndroid Build Coastguard Worker "PGluaXQ+AAtDbGFzc0IuamF2YQABTAAMTGFydC9DbGFzc0E7AAxMYXJ0L0NsYXNzQjsAFUxqYXZh" + 162*795d594fSAndroid Build Coastguard Worker "L2lvL1ByaW50U3RyZWFtOwASTGphdmEvbGFuZy9PYmplY3Q7ABJMamF2YS9sYW5nL1N0cmluZzsA" + 163*795d594fSAndroid Build Coastguard Worker "EkxqYXZhL2xhbmcvU3lzdGVtOwABVgACVkwACGdldEhlbGxvAANvdXQACnByaW50SGVsbG8AB3By" + 164*795d594fSAndroid Build Coastguard Worker "aW50bG4AdX5+RDh7ImNvbXBpbGF0aW9uLW1vZGUiOiJkZWJ1ZyIsIm1pbi1hcGkiOjEsInNoYS0x" + 165*795d594fSAndroid Build Coastguard Worker "IjoiOTY2MDhmZDdiYmNjZGQyMjc2Y2Y4OTI4M2QyYjgwY2JmYzRmYzgxYyIsInZlcnNpb24iOiIx" + 166*795d594fSAndroid Build Coastguard Worker "LjUuNC1kZXYifQAAAAIAAYGABMACAQnYAgAAAAAAAAAOAAAAAAAAAAEAAAAAAAAAAQAAABAAAABw" + 167*795d594fSAndroid Build Coastguard Worker "AAAAAgAAAAcAAACwAAAAAwAAAAMAAADMAAAABAAAAAEAAADwAAAABQAAAAUAAAD4AAAABgAAAAEA" + 168*795d594fSAndroid Build Coastguard Worker "AAAgAQAAASAAAAIAAABAAQAAAyAAAAIAAAB8AQAAARAAAAEAAACIAQAAAiAAABAAAACOAQAAACAA" + 169*795d594fSAndroid Build Coastguard Worker "AAEAAAC3AgAAAxAAAAEAAADIAgAAABAAAAEAAADMAgAA"); 170*795d594fSAndroid Build Coastguard Worker } 171