xref: /aosp_15_r20/art/test/690-hiddenapi-same-name-methods/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 java.io.File;
18*795d594fSAndroid Build Coastguard Worker import java.lang.reflect.Method;
19*795d594fSAndroid Build Coastguard Worker import java.util.Base64;
20*795d594fSAndroid Build Coastguard Worker 
21*795d594fSAndroid Build Coastguard Worker public class Main {
main(String[] args)22*795d594fSAndroid Build Coastguard Worker   public static void main(String[] args) throws ClassNotFoundException, NoSuchMethodException {
23*795d594fSAndroid Build Coastguard Worker     System.loadLibrary(args[0]);
24*795d594fSAndroid Build Coastguard Worker 
25*795d594fSAndroid Build Coastguard Worker     // Run the initialization routine. This will enable hidden API checks in
26*795d594fSAndroid Build Coastguard Worker     // the runtime, in case they are not enabled by default.
27*795d594fSAndroid Build Coastguard Worker     init();
28*795d594fSAndroid Build Coastguard Worker 
29*795d594fSAndroid Build Coastguard Worker     // Load the '-ex' APK and attach it to the boot class path.
30*795d594fSAndroid Build Coastguard Worker     appendToBootClassLoader(DEX_EXTRA, /* isCorePlatform */ false);
31*795d594fSAndroid Build Coastguard Worker 
32*795d594fSAndroid Build Coastguard Worker     // All test classes contain just methods named "foo" with different return types
33*795d594fSAndroid Build Coastguard Worker     // and access flags. Check that:
34*795d594fSAndroid Build Coastguard Worker     // (a) only the non-hidden ones are returned from getDeclaredMethods
35*795d594fSAndroid Build Coastguard Worker     //     (they have return types Number and Double), and
36*795d594fSAndroid Build Coastguard Worker     // (b) getDeclaredMethod picks virtual/non-synthetic methods over direct/synthetic
37*795d594fSAndroid Build Coastguard Worker     //     (the right one always has return type Number).
38*795d594fSAndroid Build Coastguard Worker     Class<?> covariantClass = Class.forName(JAVA_CLASS_NAME, true, BOOT_CLASS_LOADER);
39*795d594fSAndroid Build Coastguard Worker     checkMethodList(covariantClass, /* expectedLength= */ 1);
40*795d594fSAndroid Build Coastguard Worker     checkMethod(covariantClass);
41*795d594fSAndroid Build Coastguard Worker 
42*795d594fSAndroid Build Coastguard Worker     String[] classes = new String[] {
43*795d594fSAndroid Build Coastguard Worker       "VirtualMethods",
44*795d594fSAndroid Build Coastguard Worker       "DirectMethods",
45*795d594fSAndroid Build Coastguard Worker       "SyntheticMethods",
46*795d594fSAndroid Build Coastguard Worker       "NonSyntheticMethods"
47*795d594fSAndroid Build Coastguard Worker     };
48*795d594fSAndroid Build Coastguard Worker     for (String className : classes) {
49*795d594fSAndroid Build Coastguard Worker       Class<?> klass = Class.forName(className, true, BOOT_CLASS_LOADER);
50*795d594fSAndroid Build Coastguard Worker       checkMethodList(klass, /* expectedLength= */ 2);
51*795d594fSAndroid Build Coastguard Worker       checkMethod(klass);
52*795d594fSAndroid Build Coastguard Worker     }
53*795d594fSAndroid Build Coastguard Worker   }
54*795d594fSAndroid Build Coastguard Worker 
checkMethodList(Class<?> klass, int expectedLength)55*795d594fSAndroid Build Coastguard Worker   private static void checkMethodList(Class<?> klass, int expectedLength) {
56*795d594fSAndroid Build Coastguard Worker     String className = klass.getName();
57*795d594fSAndroid Build Coastguard Worker     Method[] methods = klass.getDeclaredMethods();
58*795d594fSAndroid Build Coastguard Worker     if (methods.length != expectedLength) {
59*795d594fSAndroid Build Coastguard Worker       throw new RuntimeException(className + ": expected " + expectedLength +
60*795d594fSAndroid Build Coastguard Worker           " declared method(s), got " + methods.length);
61*795d594fSAndroid Build Coastguard Worker     }
62*795d594fSAndroid Build Coastguard Worker     boolean hasNumberReturnType = false;
63*795d594fSAndroid Build Coastguard Worker     boolean hasDoubleReturnType = false;
64*795d594fSAndroid Build Coastguard Worker     for (Method method : methods) {
65*795d594fSAndroid Build Coastguard Worker       if (!METHOD_NAME.equals(method.getName())) {
66*795d594fSAndroid Build Coastguard Worker         throw new RuntimeException(className + ": expected declared method name: \"" + METHOD_NAME +
67*795d594fSAndroid Build Coastguard Worker             "\", got: \"" + method.getName() + "\"");
68*795d594fSAndroid Build Coastguard Worker       }
69*795d594fSAndroid Build Coastguard Worker       if (Number.class == method.getReturnType()) {
70*795d594fSAndroid Build Coastguard Worker         hasNumberReturnType = true;
71*795d594fSAndroid Build Coastguard Worker       } else if (Double.class == method.getReturnType()) {
72*795d594fSAndroid Build Coastguard Worker         hasDoubleReturnType = true;
73*795d594fSAndroid Build Coastguard Worker       }
74*795d594fSAndroid Build Coastguard Worker     }
75*795d594fSAndroid Build Coastguard Worker     if (methods.length >= 1 && !hasNumberReturnType) {
76*795d594fSAndroid Build Coastguard Worker       throw new RuntimeException(className + ": expected a method with return type \"Number\"");
77*795d594fSAndroid Build Coastguard Worker     }
78*795d594fSAndroid Build Coastguard Worker     if (methods.length >= 2 && !hasDoubleReturnType) {
79*795d594fSAndroid Build Coastguard Worker       throw new RuntimeException(className + ": expected a method with return type \"Double\"");
80*795d594fSAndroid Build Coastguard Worker     }
81*795d594fSAndroid Build Coastguard Worker   }
82*795d594fSAndroid Build Coastguard Worker 
checkMethod(Class<?> klass)83*795d594fSAndroid Build Coastguard Worker   private static void checkMethod(Class<?> klass) throws NoSuchMethodException {
84*795d594fSAndroid Build Coastguard Worker     String className = klass.getName();
85*795d594fSAndroid Build Coastguard Worker     Method method = klass.getDeclaredMethod(METHOD_NAME);
86*795d594fSAndroid Build Coastguard Worker     if (!METHOD_NAME.equals(method.getName())) {
87*795d594fSAndroid Build Coastguard Worker       throw new RuntimeException(className + ": expected declared method name: \"" + METHOD_NAME +
88*795d594fSAndroid Build Coastguard Worker           "\", got: \"" + method.getName() + "\"");
89*795d594fSAndroid Build Coastguard Worker     } else if (Number.class != method.getReturnType()) {
90*795d594fSAndroid Build Coastguard Worker       throw new RuntimeException(className + ": expected method return type: \"Number\", got \"" +
91*795d594fSAndroid Build Coastguard Worker           method.getReturnType().toString() + "\"");
92*795d594fSAndroid Build Coastguard Worker     }
93*795d594fSAndroid Build Coastguard Worker   }
94*795d594fSAndroid Build Coastguard Worker 
95*795d594fSAndroid Build Coastguard Worker   private static final String DEX_EXTRA = new File(System.getenv("DEX_LOCATION"),
96*795d594fSAndroid Build Coastguard Worker       "690-hiddenapi-same-name-methods-ex.jar").getAbsolutePath();
97*795d594fSAndroid Build Coastguard Worker 
98*795d594fSAndroid Build Coastguard Worker   private static ClassLoader BOOT_CLASS_LOADER = Object.class.getClassLoader();
99*795d594fSAndroid Build Coastguard Worker 
100*795d594fSAndroid Build Coastguard Worker   private static final String JAVA_CLASS_NAME = "SpecificClass";
101*795d594fSAndroid Build Coastguard Worker   private static final String METHOD_NAME = "foo";
102*795d594fSAndroid Build Coastguard Worker 
103*795d594fSAndroid Build Coastguard Worker   // Native functions. Note that these are implemented in 674-hiddenapi/hiddenapi.cc.
appendToBootClassLoader(String dexPath, boolean isCorePlatform)104*795d594fSAndroid Build Coastguard Worker   private static native void appendToBootClassLoader(String dexPath, boolean isCorePlatform);
init()105*795d594fSAndroid Build Coastguard Worker   private static native void init();
106*795d594fSAndroid Build Coastguard Worker }
107