xref: /aosp_15_r20/art/test/674-hiddenapi/src-ex/Reflection.java (revision 795d594fd825385562da6b089ea9b2033f3abf5a)
1*795d594fSAndroid Build Coastguard Worker /*
2*795d594fSAndroid Build Coastguard Worker  * Copyright (C) 2017 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.lang.reflect.Constructor;
18*795d594fSAndroid Build Coastguard Worker import java.lang.reflect.Field;
19*795d594fSAndroid Build Coastguard Worker import java.lang.reflect.InvocationTargetException;
20*795d594fSAndroid Build Coastguard Worker import java.lang.reflect.Method;
21*795d594fSAndroid Build Coastguard Worker import java.lang.reflect.Modifier;
22*795d594fSAndroid Build Coastguard Worker import java.util.Arrays;
23*795d594fSAndroid Build Coastguard Worker 
24*795d594fSAndroid Build Coastguard Worker public class Reflection {
canDiscoverWithGetDeclaredField(Class<?> klass, String name)25*795d594fSAndroid Build Coastguard Worker   public static boolean canDiscoverWithGetDeclaredField(Class<?> klass, String name) {
26*795d594fSAndroid Build Coastguard Worker     try {
27*795d594fSAndroid Build Coastguard Worker       klass.getDeclaredField(name);
28*795d594fSAndroid Build Coastguard Worker       return true;
29*795d594fSAndroid Build Coastguard Worker     } catch (NoSuchFieldException ex) {
30*795d594fSAndroid Build Coastguard Worker       return false;
31*795d594fSAndroid Build Coastguard Worker     }
32*795d594fSAndroid Build Coastguard Worker   }
33*795d594fSAndroid Build Coastguard Worker 
canDiscoverWithGetDeclaredFields(Class<?> klass, String name)34*795d594fSAndroid Build Coastguard Worker   public static boolean canDiscoverWithGetDeclaredFields(Class<?> klass, String name) {
35*795d594fSAndroid Build Coastguard Worker     for (Field f : klass.getDeclaredFields()) {
36*795d594fSAndroid Build Coastguard Worker       if (f.getName().equals(name)) {
37*795d594fSAndroid Build Coastguard Worker         return true;
38*795d594fSAndroid Build Coastguard Worker       }
39*795d594fSAndroid Build Coastguard Worker     }
40*795d594fSAndroid Build Coastguard Worker     return false;
41*795d594fSAndroid Build Coastguard Worker   }
42*795d594fSAndroid Build Coastguard Worker 
canDiscoverWithGetField(Class<?> klass, String name)43*795d594fSAndroid Build Coastguard Worker   public static boolean canDiscoverWithGetField(Class<?> klass, String name) {
44*795d594fSAndroid Build Coastguard Worker     try {
45*795d594fSAndroid Build Coastguard Worker       klass.getField(name);
46*795d594fSAndroid Build Coastguard Worker       return true;
47*795d594fSAndroid Build Coastguard Worker     } catch (NoSuchFieldException ex) {
48*795d594fSAndroid Build Coastguard Worker       return false;
49*795d594fSAndroid Build Coastguard Worker     }
50*795d594fSAndroid Build Coastguard Worker   }
51*795d594fSAndroid Build Coastguard Worker 
canDiscoverWithGetFields(Class<?> klass, String name)52*795d594fSAndroid Build Coastguard Worker   public static boolean canDiscoverWithGetFields(Class<?> klass, String name) {
53*795d594fSAndroid Build Coastguard Worker     for (Field f : klass.getFields()) {
54*795d594fSAndroid Build Coastguard Worker       if (f.getName().equals(name)) {
55*795d594fSAndroid Build Coastguard Worker         return true;
56*795d594fSAndroid Build Coastguard Worker       }
57*795d594fSAndroid Build Coastguard Worker     }
58*795d594fSAndroid Build Coastguard Worker     return false;
59*795d594fSAndroid Build Coastguard Worker   }
60*795d594fSAndroid Build Coastguard Worker 
canGetField(Class<?> klass, String name)61*795d594fSAndroid Build Coastguard Worker   public static boolean canGetField(Class<?> klass, String name) {
62*795d594fSAndroid Build Coastguard Worker     try {
63*795d594fSAndroid Build Coastguard Worker       Field f = klass.getDeclaredField(name);
64*795d594fSAndroid Build Coastguard Worker       f.setAccessible(true);
65*795d594fSAndroid Build Coastguard Worker       f.getInt(Modifier.isStatic(f.getModifiers()) ? null : klass.newInstance());
66*795d594fSAndroid Build Coastguard Worker       return true;
67*795d594fSAndroid Build Coastguard Worker     } catch (Exception ex) {
68*795d594fSAndroid Build Coastguard Worker       ex.printStackTrace();
69*795d594fSAndroid Build Coastguard Worker       return false;
70*795d594fSAndroid Build Coastguard Worker     }
71*795d594fSAndroid Build Coastguard Worker   }
72*795d594fSAndroid Build Coastguard Worker 
canSetField(Class<?> klass, String name)73*795d594fSAndroid Build Coastguard Worker   public static boolean canSetField(Class<?> klass, String name) {
74*795d594fSAndroid Build Coastguard Worker     try {
75*795d594fSAndroid Build Coastguard Worker       Field f = klass.getDeclaredField(name);
76*795d594fSAndroid Build Coastguard Worker       f.setAccessible(true);
77*795d594fSAndroid Build Coastguard Worker       f.setInt(Modifier.isStatic(f.getModifiers()) ? null : klass.newInstance(), 42);
78*795d594fSAndroid Build Coastguard Worker       return true;
79*795d594fSAndroid Build Coastguard Worker     } catch (Exception ex) {
80*795d594fSAndroid Build Coastguard Worker       ex.printStackTrace();
81*795d594fSAndroid Build Coastguard Worker       return false;
82*795d594fSAndroid Build Coastguard Worker     }
83*795d594fSAndroid Build Coastguard Worker   }
84*795d594fSAndroid Build Coastguard Worker 
canDiscoverWithGetDeclaredMethod(Class<?> klass, String name)85*795d594fSAndroid Build Coastguard Worker   public static boolean canDiscoverWithGetDeclaredMethod(Class<?> klass, String name) {
86*795d594fSAndroid Build Coastguard Worker     try {
87*795d594fSAndroid Build Coastguard Worker       klass.getDeclaredMethod(name);
88*795d594fSAndroid Build Coastguard Worker       return true;
89*795d594fSAndroid Build Coastguard Worker     } catch (NoSuchMethodException ex) {
90*795d594fSAndroid Build Coastguard Worker       return false;
91*795d594fSAndroid Build Coastguard Worker     }
92*795d594fSAndroid Build Coastguard Worker   }
93*795d594fSAndroid Build Coastguard Worker 
canDiscoverWithGetDeclaredMethods(Class<?> klass, String name)94*795d594fSAndroid Build Coastguard Worker   public static boolean canDiscoverWithGetDeclaredMethods(Class<?> klass, String name) {
95*795d594fSAndroid Build Coastguard Worker     for (Method m : klass.getDeclaredMethods()) {
96*795d594fSAndroid Build Coastguard Worker       if (m.getName().equals(name)) {
97*795d594fSAndroid Build Coastguard Worker         return true;
98*795d594fSAndroid Build Coastguard Worker       }
99*795d594fSAndroid Build Coastguard Worker     }
100*795d594fSAndroid Build Coastguard Worker     return false;
101*795d594fSAndroid Build Coastguard Worker   }
102*795d594fSAndroid Build Coastguard Worker 
canDiscoverWithGetMethod(Class<?> klass, String name)103*795d594fSAndroid Build Coastguard Worker   public static boolean canDiscoverWithGetMethod(Class<?> klass, String name) {
104*795d594fSAndroid Build Coastguard Worker     try {
105*795d594fSAndroid Build Coastguard Worker       klass.getMethod(name);
106*795d594fSAndroid Build Coastguard Worker       return true;
107*795d594fSAndroid Build Coastguard Worker     } catch (NoSuchMethodException ex) {
108*795d594fSAndroid Build Coastguard Worker       return false;
109*795d594fSAndroid Build Coastguard Worker     }
110*795d594fSAndroid Build Coastguard Worker   }
111*795d594fSAndroid Build Coastguard Worker 
canDiscoverWithGetMethods(Class<?> klass, String name)112*795d594fSAndroid Build Coastguard Worker   public static boolean canDiscoverWithGetMethods(Class<?> klass, String name) {
113*795d594fSAndroid Build Coastguard Worker     for (Method m : klass.getMethods()) {
114*795d594fSAndroid Build Coastguard Worker       if (m.getName().equals(name)) {
115*795d594fSAndroid Build Coastguard Worker         return true;
116*795d594fSAndroid Build Coastguard Worker       }
117*795d594fSAndroid Build Coastguard Worker     }
118*795d594fSAndroid Build Coastguard Worker     return false;
119*795d594fSAndroid Build Coastguard Worker   }
120*795d594fSAndroid Build Coastguard Worker 
canInvokeMethod(Class<?> klass, String name)121*795d594fSAndroid Build Coastguard Worker   public static boolean canInvokeMethod(Class<?> klass, String name) {
122*795d594fSAndroid Build Coastguard Worker     try {
123*795d594fSAndroid Build Coastguard Worker       Method m = klass.getDeclaredMethod(name);
124*795d594fSAndroid Build Coastguard Worker       m.setAccessible(true);
125*795d594fSAndroid Build Coastguard Worker       m.invoke(klass.isInterface() ? null : klass.newInstance());
126*795d594fSAndroid Build Coastguard Worker       return true;
127*795d594fSAndroid Build Coastguard Worker     } catch (Exception ex) {
128*795d594fSAndroid Build Coastguard Worker       ex.printStackTrace();
129*795d594fSAndroid Build Coastguard Worker       return false;
130*795d594fSAndroid Build Coastguard Worker     }
131*795d594fSAndroid Build Coastguard Worker   }
132*795d594fSAndroid Build Coastguard Worker 
canDiscoverWithGetDeclaredConstructor(Class<?> klass, Class<?> args[])133*795d594fSAndroid Build Coastguard Worker   public static boolean canDiscoverWithGetDeclaredConstructor(Class<?> klass, Class<?> args[]) {
134*795d594fSAndroid Build Coastguard Worker     try {
135*795d594fSAndroid Build Coastguard Worker       klass.getDeclaredConstructor(args);
136*795d594fSAndroid Build Coastguard Worker       return true;
137*795d594fSAndroid Build Coastguard Worker     } catch (NoSuchMethodException ex) {
138*795d594fSAndroid Build Coastguard Worker       return false;
139*795d594fSAndroid Build Coastguard Worker     }
140*795d594fSAndroid Build Coastguard Worker   }
141*795d594fSAndroid Build Coastguard Worker 
canDiscoverWithGetDeclaredConstructors(Class<?> klass, Class<?> args[])142*795d594fSAndroid Build Coastguard Worker   public static boolean canDiscoverWithGetDeclaredConstructors(Class<?> klass, Class<?> args[]) {
143*795d594fSAndroid Build Coastguard Worker     for (Constructor c : klass.getDeclaredConstructors()) {
144*795d594fSAndroid Build Coastguard Worker       if (Arrays.equals(c.getParameterTypes(), args)) {
145*795d594fSAndroid Build Coastguard Worker         return true;
146*795d594fSAndroid Build Coastguard Worker       }
147*795d594fSAndroid Build Coastguard Worker     }
148*795d594fSAndroid Build Coastguard Worker     return false;
149*795d594fSAndroid Build Coastguard Worker   }
150*795d594fSAndroid Build Coastguard Worker 
canDiscoverWithGetConstructor(Class<?> klass, Class<?> args[])151*795d594fSAndroid Build Coastguard Worker   public static boolean canDiscoverWithGetConstructor(Class<?> klass, Class<?> args[]) {
152*795d594fSAndroid Build Coastguard Worker     try {
153*795d594fSAndroid Build Coastguard Worker       klass.getConstructor(args);
154*795d594fSAndroid Build Coastguard Worker       return true;
155*795d594fSAndroid Build Coastguard Worker     } catch (NoSuchMethodException ex) {
156*795d594fSAndroid Build Coastguard Worker       return false;
157*795d594fSAndroid Build Coastguard Worker     }
158*795d594fSAndroid Build Coastguard Worker   }
159*795d594fSAndroid Build Coastguard Worker 
canDiscoverWithGetConstructors(Class<?> klass, Class<?> args[])160*795d594fSAndroid Build Coastguard Worker   public static boolean canDiscoverWithGetConstructors(Class<?> klass, Class<?> args[]) {
161*795d594fSAndroid Build Coastguard Worker     for (Constructor c : klass.getConstructors()) {
162*795d594fSAndroid Build Coastguard Worker       if (Arrays.equals(c.getParameterTypes(), args)) {
163*795d594fSAndroid Build Coastguard Worker         return true;
164*795d594fSAndroid Build Coastguard Worker       }
165*795d594fSAndroid Build Coastguard Worker     }
166*795d594fSAndroid Build Coastguard Worker     return false;
167*795d594fSAndroid Build Coastguard Worker   }
168*795d594fSAndroid Build Coastguard Worker 
canInvokeConstructor(Class<?> klass, Class<?> args[], Object[] initargs)169*795d594fSAndroid Build Coastguard Worker   public static boolean canInvokeConstructor(Class<?> klass, Class<?> args[], Object[] initargs) {
170*795d594fSAndroid Build Coastguard Worker     try {
171*795d594fSAndroid Build Coastguard Worker       Constructor c = klass.getDeclaredConstructor(args);
172*795d594fSAndroid Build Coastguard Worker       c.setAccessible(true);
173*795d594fSAndroid Build Coastguard Worker       c.newInstance(initargs);
174*795d594fSAndroid Build Coastguard Worker       return true;
175*795d594fSAndroid Build Coastguard Worker     } catch (Exception ex) {
176*795d594fSAndroid Build Coastguard Worker       ex.printStackTrace();
177*795d594fSAndroid Build Coastguard Worker       return false;
178*795d594fSAndroid Build Coastguard Worker     }
179*795d594fSAndroid Build Coastguard Worker   }
180*795d594fSAndroid Build Coastguard Worker 
canUseNewInstance(Class<?> klass)181*795d594fSAndroid Build Coastguard Worker   public static boolean canUseNewInstance(Class<?> klass) throws IllegalAccessException {
182*795d594fSAndroid Build Coastguard Worker     try {
183*795d594fSAndroid Build Coastguard Worker       klass.newInstance();
184*795d594fSAndroid Build Coastguard Worker       return true;
185*795d594fSAndroid Build Coastguard Worker     } catch (InstantiationException ex) {
186*795d594fSAndroid Build Coastguard Worker       return false;
187*795d594fSAndroid Build Coastguard Worker     }
188*795d594fSAndroid Build Coastguard Worker   }
189*795d594fSAndroid Build Coastguard Worker 
canDiscoverMethodWithMetaReflection(Class<?> klass, String name, boolean hardeningEnabled)190*795d594fSAndroid Build Coastguard Worker   public static boolean canDiscoverMethodWithMetaReflection(Class<?> klass, String name,
191*795d594fSAndroid Build Coastguard Worker       boolean hardeningEnabled) {
192*795d594fSAndroid Build Coastguard Worker     try {
193*795d594fSAndroid Build Coastguard Worker       setHiddenApiCheckHardening(hardeningEnabled);
194*795d594fSAndroid Build Coastguard Worker       Method metaGetDeclaredMethod =
195*795d594fSAndroid Build Coastguard Worker           Class.class.getDeclaredMethod("getDeclaredMethod", String.class, Class[].class);
196*795d594fSAndroid Build Coastguard Worker       // Assumes method without parameters.
197*795d594fSAndroid Build Coastguard Worker       return ((Method)metaGetDeclaredMethod.invoke(klass, name,  null)) != null;
198*795d594fSAndroid Build Coastguard Worker     } catch (NoSuchMethodException | InvocationTargetException | IllegalAccessException ex) {
199*795d594fSAndroid Build Coastguard Worker       return false;
200*795d594fSAndroid Build Coastguard Worker     }
201*795d594fSAndroid Build Coastguard Worker   }
202*795d594fSAndroid Build Coastguard Worker 
canDiscoverFieldWithMetaReflection(Class<?> klass, String name, boolean hardeningEnabled)203*795d594fSAndroid Build Coastguard Worker   public static boolean canDiscoverFieldWithMetaReflection(Class<?> klass, String name,
204*795d594fSAndroid Build Coastguard Worker       boolean hardeningEnabled) {
205*795d594fSAndroid Build Coastguard Worker     try {
206*795d594fSAndroid Build Coastguard Worker       setHiddenApiCheckHardening(hardeningEnabled);
207*795d594fSAndroid Build Coastguard Worker       Method metaGetDeclaredField =
208*795d594fSAndroid Build Coastguard Worker           Class.class.getDeclaredMethod("getDeclaredField", String.class);
209*795d594fSAndroid Build Coastguard Worker       return ((Field)metaGetDeclaredField.invoke(klass, name)) != null;
210*795d594fSAndroid Build Coastguard Worker     } catch (NoSuchMethodException | InvocationTargetException | IllegalAccessException ex) {
211*795d594fSAndroid Build Coastguard Worker       return false;
212*795d594fSAndroid Build Coastguard Worker     }
213*795d594fSAndroid Build Coastguard Worker   }
214*795d594fSAndroid Build Coastguard Worker 
canDiscoverConstructorWithMetaReflection(Class<?> klass, Class<?> args[], boolean hardeningEnabled)215*795d594fSAndroid Build Coastguard Worker   public static boolean canDiscoverConstructorWithMetaReflection(Class<?> klass, Class<?> args[],
216*795d594fSAndroid Build Coastguard Worker       boolean hardeningEnabled) {
217*795d594fSAndroid Build Coastguard Worker     try {
218*795d594fSAndroid Build Coastguard Worker       setHiddenApiCheckHardening(hardeningEnabled);
219*795d594fSAndroid Build Coastguard Worker       Method metaGetDeclaredConstructor =
220*795d594fSAndroid Build Coastguard Worker           Class.class.getDeclaredMethod("getDeclaredConstructor", Class[].class);
221*795d594fSAndroid Build Coastguard Worker       return ((Constructor<?>)metaGetDeclaredConstructor.invoke(klass, (Object)args)) != null;
222*795d594fSAndroid Build Coastguard Worker     } catch (NoSuchMethodException | InvocationTargetException | IllegalAccessException ex) {
223*795d594fSAndroid Build Coastguard Worker       return false;
224*795d594fSAndroid Build Coastguard Worker     }
225*795d594fSAndroid Build Coastguard Worker   }
226*795d594fSAndroid Build Coastguard Worker 
getHiddenApiAccessFlags()227*795d594fSAndroid Build Coastguard Worker   private static native int getHiddenApiAccessFlags();
setHiddenApiCheckHardening(boolean value)228*795d594fSAndroid Build Coastguard Worker   private static native void setHiddenApiCheckHardening(boolean value);
229*795d594fSAndroid Build Coastguard Worker 
canObserveFieldHiddenAccessFlags(Class<?> klass, String name)230*795d594fSAndroid Build Coastguard Worker   public static boolean canObserveFieldHiddenAccessFlags(Class<?> klass, String name)
231*795d594fSAndroid Build Coastguard Worker       throws Exception {
232*795d594fSAndroid Build Coastguard Worker     return (klass.getDeclaredField(name).getModifiers() & getHiddenApiAccessFlags()) != 0;
233*795d594fSAndroid Build Coastguard Worker   }
234*795d594fSAndroid Build Coastguard Worker 
canObserveMethodHiddenAccessFlags(Class<?> klass, String name)235*795d594fSAndroid Build Coastguard Worker   public static boolean canObserveMethodHiddenAccessFlags(Class<?> klass, String name)
236*795d594fSAndroid Build Coastguard Worker       throws Exception {
237*795d594fSAndroid Build Coastguard Worker     return (klass.getDeclaredMethod(name).getModifiers() & getHiddenApiAccessFlags()) != 0;
238*795d594fSAndroid Build Coastguard Worker   }
239*795d594fSAndroid Build Coastguard Worker 
canObserveConstructorHiddenAccessFlags(Class<?> klass, Class<?> args[])240*795d594fSAndroid Build Coastguard Worker   public static boolean canObserveConstructorHiddenAccessFlags(Class<?> klass, Class<?> args[])
241*795d594fSAndroid Build Coastguard Worker       throws Exception {
242*795d594fSAndroid Build Coastguard Worker     return (klass.getConstructor(args).getModifiers() & getHiddenApiAccessFlags()) != 0;
243*795d594fSAndroid Build Coastguard Worker   }
244*795d594fSAndroid Build Coastguard Worker }
245