1 /* 2 * Copyright (C) 2017 The Android Open Source Project 3 * 4 * Licensed under the Apache License, Version 2.0 (the "License"); 5 * you may not use this file except in compliance with the License. 6 * You may obtain a copy of the License at 7 * 8 * http://www.apache.org/licenses/LICENSE-2.0 9 * 10 * Unless required by applicable law or agreed to in writing, software 11 * distributed under the License is distributed on an "AS IS" BASIS, 12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 * See the License for the specific language governing permissions and 14 * limitations under the License. 15 */ 16 17 import java.lang.reflect.Constructor; 18 import java.lang.reflect.Field; 19 import java.lang.reflect.InvocationTargetException; 20 import java.lang.reflect.Method; 21 import java.lang.reflect.Modifier; 22 import java.util.Arrays; 23 24 public class Reflection { canDiscoverWithGetDeclaredField(Class<?> klass, String name)25 public static boolean canDiscoverWithGetDeclaredField(Class<?> klass, String name) { 26 try { 27 klass.getDeclaredField(name); 28 return true; 29 } catch (NoSuchFieldException ex) { 30 return false; 31 } 32 } 33 canDiscoverWithGetDeclaredFields(Class<?> klass, String name)34 public static boolean canDiscoverWithGetDeclaredFields(Class<?> klass, String name) { 35 for (Field f : klass.getDeclaredFields()) { 36 if (f.getName().equals(name)) { 37 return true; 38 } 39 } 40 return false; 41 } 42 canDiscoverWithGetField(Class<?> klass, String name)43 public static boolean canDiscoverWithGetField(Class<?> klass, String name) { 44 try { 45 klass.getField(name); 46 return true; 47 } catch (NoSuchFieldException ex) { 48 return false; 49 } 50 } 51 canDiscoverWithGetFields(Class<?> klass, String name)52 public static boolean canDiscoverWithGetFields(Class<?> klass, String name) { 53 for (Field f : klass.getFields()) { 54 if (f.getName().equals(name)) { 55 return true; 56 } 57 } 58 return false; 59 } 60 canGetField(Class<?> klass, String name)61 public static boolean canGetField(Class<?> klass, String name) { 62 try { 63 Field f = klass.getDeclaredField(name); 64 f.setAccessible(true); 65 f.getInt(Modifier.isStatic(f.getModifiers()) ? null : klass.newInstance()); 66 return true; 67 } catch (Exception ex) { 68 ex.printStackTrace(); 69 return false; 70 } 71 } 72 canSetField(Class<?> klass, String name)73 public static boolean canSetField(Class<?> klass, String name) { 74 try { 75 Field f = klass.getDeclaredField(name); 76 f.setAccessible(true); 77 f.setInt(Modifier.isStatic(f.getModifiers()) ? null : klass.newInstance(), 42); 78 return true; 79 } catch (Exception ex) { 80 ex.printStackTrace(); 81 return false; 82 } 83 } 84 canDiscoverWithGetDeclaredMethod(Class<?> klass, String name)85 public static boolean canDiscoverWithGetDeclaredMethod(Class<?> klass, String name) { 86 try { 87 klass.getDeclaredMethod(name); 88 return true; 89 } catch (NoSuchMethodException ex) { 90 return false; 91 } 92 } 93 canDiscoverWithGetDeclaredMethods(Class<?> klass, String name)94 public static boolean canDiscoverWithGetDeclaredMethods(Class<?> klass, String name) { 95 for (Method m : klass.getDeclaredMethods()) { 96 if (m.getName().equals(name)) { 97 return true; 98 } 99 } 100 return false; 101 } 102 canDiscoverWithGetMethod(Class<?> klass, String name)103 public static boolean canDiscoverWithGetMethod(Class<?> klass, String name) { 104 try { 105 klass.getMethod(name); 106 return true; 107 } catch (NoSuchMethodException ex) { 108 return false; 109 } 110 } 111 canDiscoverWithGetMethods(Class<?> klass, String name)112 public static boolean canDiscoverWithGetMethods(Class<?> klass, String name) { 113 for (Method m : klass.getMethods()) { 114 if (m.getName().equals(name)) { 115 return true; 116 } 117 } 118 return false; 119 } 120 canInvokeMethod(Class<?> klass, String name)121 public static boolean canInvokeMethod(Class<?> klass, String name) { 122 try { 123 Method m = klass.getDeclaredMethod(name); 124 m.setAccessible(true); 125 m.invoke(klass.isInterface() ? null : klass.newInstance()); 126 return true; 127 } catch (Exception ex) { 128 ex.printStackTrace(); 129 return false; 130 } 131 } 132 canDiscoverWithGetDeclaredConstructor(Class<?> klass, Class<?> args[])133 public static boolean canDiscoverWithGetDeclaredConstructor(Class<?> klass, Class<?> args[]) { 134 try { 135 klass.getDeclaredConstructor(args); 136 return true; 137 } catch (NoSuchMethodException ex) { 138 return false; 139 } 140 } 141 canDiscoverWithGetDeclaredConstructors(Class<?> klass, Class<?> args[])142 public static boolean canDiscoverWithGetDeclaredConstructors(Class<?> klass, Class<?> args[]) { 143 for (Constructor c : klass.getDeclaredConstructors()) { 144 if (Arrays.equals(c.getParameterTypes(), args)) { 145 return true; 146 } 147 } 148 return false; 149 } 150 canDiscoverWithGetConstructor(Class<?> klass, Class<?> args[])151 public static boolean canDiscoverWithGetConstructor(Class<?> klass, Class<?> args[]) { 152 try { 153 klass.getConstructor(args); 154 return true; 155 } catch (NoSuchMethodException ex) { 156 return false; 157 } 158 } 159 canDiscoverWithGetConstructors(Class<?> klass, Class<?> args[])160 public static boolean canDiscoverWithGetConstructors(Class<?> klass, Class<?> args[]) { 161 for (Constructor c : klass.getConstructors()) { 162 if (Arrays.equals(c.getParameterTypes(), args)) { 163 return true; 164 } 165 } 166 return false; 167 } 168 canInvokeConstructor(Class<?> klass, Class<?> args[], Object[] initargs)169 public static boolean canInvokeConstructor(Class<?> klass, Class<?> args[], Object[] initargs) { 170 try { 171 Constructor c = klass.getDeclaredConstructor(args); 172 c.setAccessible(true); 173 c.newInstance(initargs); 174 return true; 175 } catch (Exception ex) { 176 ex.printStackTrace(); 177 return false; 178 } 179 } 180 canUseNewInstance(Class<?> klass)181 public static boolean canUseNewInstance(Class<?> klass) throws IllegalAccessException { 182 try { 183 klass.newInstance(); 184 return true; 185 } catch (InstantiationException ex) { 186 return false; 187 } 188 } 189 canDiscoverMethodWithMetaReflection(Class<?> klass, String name, boolean hardeningEnabled)190 public static boolean canDiscoverMethodWithMetaReflection(Class<?> klass, String name, 191 boolean hardeningEnabled) { 192 try { 193 setHiddenApiCheckHardening(hardeningEnabled); 194 Method metaGetDeclaredMethod = 195 Class.class.getDeclaredMethod("getDeclaredMethod", String.class, Class[].class); 196 // Assumes method without parameters. 197 return ((Method)metaGetDeclaredMethod.invoke(klass, name, null)) != null; 198 } catch (NoSuchMethodException | InvocationTargetException | IllegalAccessException ex) { 199 return false; 200 } 201 } 202 canDiscoverFieldWithMetaReflection(Class<?> klass, String name, boolean hardeningEnabled)203 public static boolean canDiscoverFieldWithMetaReflection(Class<?> klass, String name, 204 boolean hardeningEnabled) { 205 try { 206 setHiddenApiCheckHardening(hardeningEnabled); 207 Method metaGetDeclaredField = 208 Class.class.getDeclaredMethod("getDeclaredField", String.class); 209 return ((Field)metaGetDeclaredField.invoke(klass, name)) != null; 210 } catch (NoSuchMethodException | InvocationTargetException | IllegalAccessException ex) { 211 return false; 212 } 213 } 214 canDiscoverConstructorWithMetaReflection(Class<?> klass, Class<?> args[], boolean hardeningEnabled)215 public static boolean canDiscoverConstructorWithMetaReflection(Class<?> klass, Class<?> args[], 216 boolean hardeningEnabled) { 217 try { 218 setHiddenApiCheckHardening(hardeningEnabled); 219 Method metaGetDeclaredConstructor = 220 Class.class.getDeclaredMethod("getDeclaredConstructor", Class[].class); 221 return ((Constructor<?>)metaGetDeclaredConstructor.invoke(klass, (Object)args)) != null; 222 } catch (NoSuchMethodException | InvocationTargetException | IllegalAccessException ex) { 223 return false; 224 } 225 } 226 getHiddenApiAccessFlags()227 private static native int getHiddenApiAccessFlags(); setHiddenApiCheckHardening(boolean value)228 private static native void setHiddenApiCheckHardening(boolean value); 229 canObserveFieldHiddenAccessFlags(Class<?> klass, String name)230 public static boolean canObserveFieldHiddenAccessFlags(Class<?> klass, String name) 231 throws Exception { 232 return (klass.getDeclaredField(name).getModifiers() & getHiddenApiAccessFlags()) != 0; 233 } 234 canObserveMethodHiddenAccessFlags(Class<?> klass, String name)235 public static boolean canObserveMethodHiddenAccessFlags(Class<?> klass, String name) 236 throws Exception { 237 return (klass.getDeclaredMethod(name).getModifiers() & getHiddenApiAccessFlags()) != 0; 238 } 239 canObserveConstructorHiddenAccessFlags(Class<?> klass, Class<?> args[])240 public static boolean canObserveConstructorHiddenAccessFlags(Class<?> klass, Class<?> args[]) 241 throws Exception { 242 return (klass.getConstructor(args).getModifiers() & getHiddenApiAccessFlags()) != 0; 243 } 244 } 245