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