xref: /aosp_15_r20/art/test/692-vdex-inmem-loader/src/Main.java (revision 795d594fd825385562da6b089ea9b2033f3abf5a)
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