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 dalvik.system.VMRuntime; 18*795d594fSAndroid Build Coastguard Worker import java.lang.invoke.MethodHandles; 19*795d594fSAndroid Build Coastguard Worker import java.lang.invoke.MethodType; 20*795d594fSAndroid Build Coastguard Worker import java.util.function.Consumer; 21*795d594fSAndroid Build Coastguard Worker 22*795d594fSAndroid Build Coastguard Worker public class ChildClass { 23*795d594fSAndroid Build Coastguard Worker enum PrimitiveType { 24*795d594fSAndroid Build Coastguard Worker TInteger('I', Integer.TYPE, Integer.valueOf(0)), 25*795d594fSAndroid Build Coastguard Worker TLong('J', Long.TYPE, Long.valueOf(0)), 26*795d594fSAndroid Build Coastguard Worker TFloat('F', Float.TYPE, Float.valueOf(0)), 27*795d594fSAndroid Build Coastguard Worker TDouble('D', Double.TYPE, Double.valueOf(0)), 28*795d594fSAndroid Build Coastguard Worker TBoolean('Z', Boolean.TYPE, Boolean.valueOf(false)), 29*795d594fSAndroid Build Coastguard Worker TByte('B', Byte.TYPE, Byte.valueOf((byte) 0)), 30*795d594fSAndroid Build Coastguard Worker TShort('S', Short.TYPE, Short.valueOf((short) 0)), 31*795d594fSAndroid Build Coastguard Worker TCharacter('C', Character.TYPE, Character.valueOf('0')); 32*795d594fSAndroid Build Coastguard Worker PrimitiveType(char shorty, Class klass, Object value)33*795d594fSAndroid Build Coastguard Worker PrimitiveType(char shorty, Class klass, Object value) { 34*795d594fSAndroid Build Coastguard Worker mShorty = shorty; 35*795d594fSAndroid Build Coastguard Worker mClass = klass; 36*795d594fSAndroid Build Coastguard Worker mDefaultValue = value; 37*795d594fSAndroid Build Coastguard Worker } 38*795d594fSAndroid Build Coastguard Worker 39*795d594fSAndroid Build Coastguard Worker public char mShorty; 40*795d594fSAndroid Build Coastguard Worker public Class mClass; 41*795d594fSAndroid Build Coastguard Worker public Object mDefaultValue; 42*795d594fSAndroid Build Coastguard Worker } 43*795d594fSAndroid Build Coastguard Worker 44*795d594fSAndroid Build Coastguard Worker enum Hiddenness { 45*795d594fSAndroid Build Coastguard Worker Sdk(PrimitiveType.TShort), 46*795d594fSAndroid Build Coastguard Worker Unsupported(PrimitiveType.TBoolean), 47*795d594fSAndroid Build Coastguard Worker ConditionallyBlocked(PrimitiveType.TByte), 48*795d594fSAndroid Build Coastguard Worker Blocklist(PrimitiveType.TCharacter), 49*795d594fSAndroid Build Coastguard Worker BlocklistAndCorePlatformApi(PrimitiveType.TInteger); 50*795d594fSAndroid Build Coastguard Worker Hiddenness(PrimitiveType type)51*795d594fSAndroid Build Coastguard Worker Hiddenness(PrimitiveType type) { mAssociatedType = type; } 52*795d594fSAndroid Build Coastguard Worker public PrimitiveType mAssociatedType; 53*795d594fSAndroid Build Coastguard Worker } 54*795d594fSAndroid Build Coastguard Worker 55*795d594fSAndroid Build Coastguard Worker enum Visibility { 56*795d594fSAndroid Build Coastguard Worker Public(PrimitiveType.TInteger), 57*795d594fSAndroid Build Coastguard Worker Package(PrimitiveType.TFloat), 58*795d594fSAndroid Build Coastguard Worker Protected(PrimitiveType.TLong), 59*795d594fSAndroid Build Coastguard Worker Private(PrimitiveType.TDouble); 60*795d594fSAndroid Build Coastguard Worker Visibility(PrimitiveType type)61*795d594fSAndroid Build Coastguard Worker Visibility(PrimitiveType type) { mAssociatedType = type; } 62*795d594fSAndroid Build Coastguard Worker public PrimitiveType mAssociatedType; 63*795d594fSAndroid Build Coastguard Worker } 64*795d594fSAndroid Build Coastguard Worker 65*795d594fSAndroid Build Coastguard Worker enum Behaviour { 66*795d594fSAndroid Build Coastguard Worker Granted, 67*795d594fSAndroid Build Coastguard Worker Warning, 68*795d594fSAndroid Build Coastguard Worker Denied, 69*795d594fSAndroid Build Coastguard Worker } 70*795d594fSAndroid Build Coastguard Worker 71*795d594fSAndroid Build Coastguard Worker // This needs to be kept in sync with DexDomain in Main. 72*795d594fSAndroid Build Coastguard Worker enum DexDomain { 73*795d594fSAndroid Build Coastguard Worker CorePlatform, 74*795d594fSAndroid Build Coastguard Worker Platform, 75*795d594fSAndroid Build Coastguard Worker Application 76*795d594fSAndroid Build Coastguard Worker } 77*795d594fSAndroid Build Coastguard Worker 78*795d594fSAndroid Build Coastguard Worker private static final boolean booleanValues[] = new boolean[] { false, true }; 79*795d594fSAndroid Build Coastguard Worker runTest(String libFileName, int parentDomainOrdinal, int childDomainOrdinal, boolean everythingSdked)80*795d594fSAndroid Build Coastguard Worker public static void runTest(String libFileName, int parentDomainOrdinal, 81*795d594fSAndroid Build Coastguard Worker int childDomainOrdinal, boolean everythingSdked) throws Exception { 82*795d594fSAndroid Build Coastguard Worker System.load(libFileName); 83*795d594fSAndroid Build Coastguard Worker 84*795d594fSAndroid Build Coastguard Worker parentDomain = DexDomain.values()[parentDomainOrdinal]; 85*795d594fSAndroid Build Coastguard Worker childDomain = DexDomain.values()[childDomainOrdinal]; 86*795d594fSAndroid Build Coastguard Worker 87*795d594fSAndroid Build Coastguard Worker configMessage = "parentDomain=" + parentDomain.name() + ", childDomain=" + childDomain.name() 88*795d594fSAndroid Build Coastguard Worker + ", everythingSdked=" + everythingSdked; 89*795d594fSAndroid Build Coastguard Worker 90*795d594fSAndroid Build Coastguard Worker // Check expectations about loading into boot class path. 91*795d594fSAndroid Build Coastguard Worker boolean isParentInBoot = (ParentClass.class.getClassLoader().getParent() == null); 92*795d594fSAndroid Build Coastguard Worker boolean expectedParentInBoot = (parentDomain != DexDomain.Application); 93*795d594fSAndroid Build Coastguard Worker if (isParentInBoot != expectedParentInBoot) { 94*795d594fSAndroid Build Coastguard Worker throw new RuntimeException("Expected ParentClass " + 95*795d594fSAndroid Build Coastguard Worker (expectedParentInBoot ? "" : "not ") + "in boot class path"); 96*795d594fSAndroid Build Coastguard Worker } 97*795d594fSAndroid Build Coastguard Worker boolean isChildInBoot = (ChildClass.class.getClassLoader().getParent() == null); 98*795d594fSAndroid Build Coastguard Worker boolean expectedChildInBoot = (childDomain != DexDomain.Application); 99*795d594fSAndroid Build Coastguard Worker if (isChildInBoot != expectedChildInBoot) { 100*795d594fSAndroid Build Coastguard Worker throw new RuntimeException("Expected ChildClass " + (expectedChildInBoot ? "" : "not ") + 101*795d594fSAndroid Build Coastguard Worker "in boot class path"); 102*795d594fSAndroid Build Coastguard Worker } 103*795d594fSAndroid Build Coastguard Worker ChildClass.everythingSdked = everythingSdked; 104*795d594fSAndroid Build Coastguard Worker 105*795d594fSAndroid Build Coastguard Worker boolean isSameBoot = (isParentInBoot == isChildInBoot); 106*795d594fSAndroid Build Coastguard Worker 107*795d594fSAndroid Build Coastguard Worker // For compat reasons, meta-reflection should still be usable by apps if hidden api check 108*795d594fSAndroid Build Coastguard Worker // hardening is disabled (i.e. target SDK is Q or earlier). The only configuration where this 109*795d594fSAndroid Build Coastguard Worker // workaround used to work is for ChildClass in the Application domain and ParentClass in the 110*795d594fSAndroid Build Coastguard Worker // Platform domain, so only test that configuration with hidden api check hardening disabled. 111*795d594fSAndroid Build Coastguard Worker boolean testHiddenApiCheckHardeningDisabled = 112*795d594fSAndroid Build Coastguard Worker (childDomain == DexDomain.Application) && (parentDomain == DexDomain.Platform); 113*795d594fSAndroid Build Coastguard Worker 114*795d594fSAndroid Build Coastguard Worker // Run meaningful combinations of access flags. 115*795d594fSAndroid Build Coastguard Worker for (Hiddenness hiddenness : Hiddenness.values()) { 116*795d594fSAndroid Build Coastguard Worker final Behaviour expected; 117*795d594fSAndroid Build Coastguard Worker final boolean invokesMemberCallback; 118*795d594fSAndroid Build Coastguard Worker // Warnings are now disabled whenever access is granted, even for 119*795d594fSAndroid Build Coastguard Worker // greylisted APIs. This is the behaviour for release builds. 120*795d594fSAndroid Build Coastguard Worker if (everythingSdked || hiddenness == Hiddenness.Sdk) { 121*795d594fSAndroid Build Coastguard Worker expected = Behaviour.Granted; 122*795d594fSAndroid Build Coastguard Worker invokesMemberCallback = false; 123*795d594fSAndroid Build Coastguard Worker } else if (parentDomain == DexDomain.CorePlatform && childDomain == DexDomain.Platform) { 124*795d594fSAndroid Build Coastguard Worker expected = (hiddenness == Hiddenness.BlocklistAndCorePlatformApi) 125*795d594fSAndroid Build Coastguard Worker ? Behaviour.Granted : Behaviour.Denied; 126*795d594fSAndroid Build Coastguard Worker invokesMemberCallback = false; 127*795d594fSAndroid Build Coastguard Worker } else if (isSameBoot) { 128*795d594fSAndroid Build Coastguard Worker expected = Behaviour.Granted; 129*795d594fSAndroid Build Coastguard Worker invokesMemberCallback = false; 130*795d594fSAndroid Build Coastguard Worker } else if (hiddenness == Hiddenness.Blocklist || 131*795d594fSAndroid Build Coastguard Worker hiddenness == Hiddenness.BlocklistAndCorePlatformApi) { 132*795d594fSAndroid Build Coastguard Worker expected = Behaviour.Denied; 133*795d594fSAndroid Build Coastguard Worker invokesMemberCallback = true; 134*795d594fSAndroid Build Coastguard Worker } else { 135*795d594fSAndroid Build Coastguard Worker expected = Behaviour.Warning; 136*795d594fSAndroid Build Coastguard Worker invokesMemberCallback = true; 137*795d594fSAndroid Build Coastguard Worker } 138*795d594fSAndroid Build Coastguard Worker 139*795d594fSAndroid Build Coastguard Worker for (boolean isStatic : booleanValues) { 140*795d594fSAndroid Build Coastguard Worker String suffix = (isStatic ? "Static" : "") + hiddenness.name(); 141*795d594fSAndroid Build Coastguard Worker 142*795d594fSAndroid Build Coastguard Worker for (Visibility visibility : Visibility.values()) { 143*795d594fSAndroid Build Coastguard Worker // Test reflection and JNI on methods and fields 144*795d594fSAndroid Build Coastguard Worker for (Class klass : new Class<?>[] { ParentClass.class, ParentInterface.class }) { 145*795d594fSAndroid Build Coastguard Worker String baseName = visibility.name() + suffix; 146*795d594fSAndroid Build Coastguard Worker checkField(klass, "field" + baseName, isStatic, visibility, expected, 147*795d594fSAndroid Build Coastguard Worker invokesMemberCallback, testHiddenApiCheckHardeningDisabled); 148*795d594fSAndroid Build Coastguard Worker checkMethod(klass, "method" + baseName, isStatic, visibility, expected, 149*795d594fSAndroid Build Coastguard Worker invokesMemberCallback, testHiddenApiCheckHardeningDisabled); 150*795d594fSAndroid Build Coastguard Worker } 151*795d594fSAndroid Build Coastguard Worker 152*795d594fSAndroid Build Coastguard Worker // Check whether one can use a class constructor. 153*795d594fSAndroid Build Coastguard Worker checkConstructor(ParentClass.class, visibility, hiddenness, expected, 154*795d594fSAndroid Build Coastguard Worker testHiddenApiCheckHardeningDisabled); 155*795d594fSAndroid Build Coastguard Worker 156*795d594fSAndroid Build Coastguard Worker // Check whether one can use an interface default method. 157*795d594fSAndroid Build Coastguard Worker String name = "method" + visibility.name() + "Default" + hiddenness.name(); 158*795d594fSAndroid Build Coastguard Worker checkMethod(ParentInterface.class, name, /*isStatic*/ false, visibility, expected, 159*795d594fSAndroid Build Coastguard Worker invokesMemberCallback, testHiddenApiCheckHardeningDisabled); 160*795d594fSAndroid Build Coastguard Worker } 161*795d594fSAndroid Build Coastguard Worker 162*795d594fSAndroid Build Coastguard Worker // Test whether static linking succeeds. 163*795d594fSAndroid Build Coastguard Worker checkLinking("LinkFieldGet" + suffix, /*takesParameter*/ false, expected); 164*795d594fSAndroid Build Coastguard Worker checkLinking("LinkFieldSet" + suffix, /*takesParameter*/ true, expected); 165*795d594fSAndroid Build Coastguard Worker checkLinking("LinkMethod" + suffix, /*takesParameter*/ false, expected); 166*795d594fSAndroid Build Coastguard Worker checkLinking("LinkMethodInterface" + suffix, /*takesParameter*/ false, expected); 167*795d594fSAndroid Build Coastguard Worker } 168*795d594fSAndroid Build Coastguard Worker 169*795d594fSAndroid Build Coastguard Worker // Check whether Class.newInstance succeeds. 170*795d594fSAndroid Build Coastguard Worker checkNullaryConstructor(Class.forName("NullaryConstructor" + hiddenness.name()), expected); 171*795d594fSAndroid Build Coastguard Worker } 172*795d594fSAndroid Build Coastguard Worker } 173*795d594fSAndroid Build Coastguard Worker 174*795d594fSAndroid Build Coastguard Worker static final class RecordingConsumer implements Consumer<String> { 175*795d594fSAndroid Build Coastguard Worker public String recordedValue = null; 176*795d594fSAndroid Build Coastguard Worker 177*795d594fSAndroid Build Coastguard Worker @Override accept(String value)178*795d594fSAndroid Build Coastguard Worker public void accept(String value) { 179*795d594fSAndroid Build Coastguard Worker recordedValue = value; 180*795d594fSAndroid Build Coastguard Worker } 181*795d594fSAndroid Build Coastguard Worker } 182*795d594fSAndroid Build Coastguard Worker checkMemberCallback(Class<?> klass, String name, boolean isPublic, boolean isField, boolean expectedCallback)183*795d594fSAndroid Build Coastguard Worker private static void checkMemberCallback(Class<?> klass, String name, 184*795d594fSAndroid Build Coastguard Worker boolean isPublic, boolean isField, boolean expectedCallback) { 185*795d594fSAndroid Build Coastguard Worker try { 186*795d594fSAndroid Build Coastguard Worker RecordingConsumer consumer = new RecordingConsumer(); 187*795d594fSAndroid Build Coastguard Worker VMRuntime.setNonSdkApiUsageConsumer(consumer); 188*795d594fSAndroid Build Coastguard Worker try { 189*795d594fSAndroid Build Coastguard Worker if (isPublic) { 190*795d594fSAndroid Build Coastguard Worker if (isField) { 191*795d594fSAndroid Build Coastguard Worker klass.getField(name); 192*795d594fSAndroid Build Coastguard Worker } else { 193*795d594fSAndroid Build Coastguard Worker klass.getMethod(name); 194*795d594fSAndroid Build Coastguard Worker } 195*795d594fSAndroid Build Coastguard Worker } else { 196*795d594fSAndroid Build Coastguard Worker if (isField) { 197*795d594fSAndroid Build Coastguard Worker klass.getDeclaredField(name); 198*795d594fSAndroid Build Coastguard Worker } else { 199*795d594fSAndroid Build Coastguard Worker klass.getDeclaredMethod(name); 200*795d594fSAndroid Build Coastguard Worker } 201*795d594fSAndroid Build Coastguard Worker } 202*795d594fSAndroid Build Coastguard Worker } catch (NoSuchFieldException|NoSuchMethodException ignored) { 203*795d594fSAndroid Build Coastguard Worker // We're not concerned whether an exception is thrown or not - we're 204*795d594fSAndroid Build Coastguard Worker // only interested in whether the callback is invoked. 205*795d594fSAndroid Build Coastguard Worker } 206*795d594fSAndroid Build Coastguard Worker 207*795d594fSAndroid Build Coastguard Worker boolean actualCallback = consumer.recordedValue != null && 208*795d594fSAndroid Build Coastguard Worker consumer.recordedValue.contains(name); 209*795d594fSAndroid Build Coastguard Worker if (expectedCallback != actualCallback) { 210*795d594fSAndroid Build Coastguard Worker if (expectedCallback) { 211*795d594fSAndroid Build Coastguard Worker throw new RuntimeException("Expected callback for member: " + name); 212*795d594fSAndroid Build Coastguard Worker } else { 213*795d594fSAndroid Build Coastguard Worker throw new RuntimeException("Did not expect callback for member: " + name); 214*795d594fSAndroid Build Coastguard Worker } 215*795d594fSAndroid Build Coastguard Worker } 216*795d594fSAndroid Build Coastguard Worker } finally { 217*795d594fSAndroid Build Coastguard Worker VMRuntime.setNonSdkApiUsageConsumer(null); 218*795d594fSAndroid Build Coastguard Worker } 219*795d594fSAndroid Build Coastguard Worker } 220*795d594fSAndroid Build Coastguard Worker checkField(Class<?> klass, String name, boolean isStatic, Visibility visibility, Behaviour behaviour, boolean invokesMemberCallback, boolean testHiddenApiCheckHardeningDisabled)221*795d594fSAndroid Build Coastguard Worker private static void checkField(Class<?> klass, String name, boolean isStatic, 222*795d594fSAndroid Build Coastguard Worker Visibility visibility, Behaviour behaviour, boolean invokesMemberCallback, 223*795d594fSAndroid Build Coastguard Worker boolean testHiddenApiCheckHardeningDisabled) throws Exception { 224*795d594fSAndroid Build Coastguard Worker 225*795d594fSAndroid Build Coastguard Worker boolean isPublic = (visibility == Visibility.Public); 226*795d594fSAndroid Build Coastguard Worker boolean canDiscover = (behaviour != Behaviour.Denied); 227*795d594fSAndroid Build Coastguard Worker 228*795d594fSAndroid Build Coastguard Worker if (klass.isInterface() && (!isStatic || !isPublic)) { 229*795d594fSAndroid Build Coastguard Worker // Interfaces only have public static fields. 230*795d594fSAndroid Build Coastguard Worker return; 231*795d594fSAndroid Build Coastguard Worker } 232*795d594fSAndroid Build Coastguard Worker 233*795d594fSAndroid Build Coastguard Worker // Test discovery with reflection. 234*795d594fSAndroid Build Coastguard Worker 235*795d594fSAndroid Build Coastguard Worker if (Reflection.canDiscoverWithGetDeclaredField(klass, name) != canDiscover) { 236*795d594fSAndroid Build Coastguard Worker throwDiscoveryException(klass, name, true, "getDeclaredField()", canDiscover); 237*795d594fSAndroid Build Coastguard Worker } 238*795d594fSAndroid Build Coastguard Worker 239*795d594fSAndroid Build Coastguard Worker if (Reflection.canDiscoverWithGetDeclaredFields(klass, name) != canDiscover) { 240*795d594fSAndroid Build Coastguard Worker throwDiscoveryException(klass, name, true, "getDeclaredFields()", canDiscover); 241*795d594fSAndroid Build Coastguard Worker } 242*795d594fSAndroid Build Coastguard Worker 243*795d594fSAndroid Build Coastguard Worker if (Reflection.canDiscoverWithGetField(klass, name) != (canDiscover && isPublic)) { 244*795d594fSAndroid Build Coastguard Worker throwDiscoveryException(klass, name, true, "getField()", (canDiscover && isPublic)); 245*795d594fSAndroid Build Coastguard Worker } 246*795d594fSAndroid Build Coastguard Worker 247*795d594fSAndroid Build Coastguard Worker if (Reflection.canDiscoverWithGetFields(klass, name) != (canDiscover && isPublic)) { 248*795d594fSAndroid Build Coastguard Worker throwDiscoveryException(klass, name, true, "getFields()", (canDiscover && isPublic)); 249*795d594fSAndroid Build Coastguard Worker } 250*795d594fSAndroid Build Coastguard Worker 251*795d594fSAndroid Build Coastguard Worker // Test discovery with JNI. 252*795d594fSAndroid Build Coastguard Worker 253*795d594fSAndroid Build Coastguard Worker if (JNI.canDiscoverField(klass, name, isStatic) != canDiscover) { 254*795d594fSAndroid Build Coastguard Worker throwDiscoveryException(klass, name, true, "JNI", canDiscover); 255*795d594fSAndroid Build Coastguard Worker } 256*795d594fSAndroid Build Coastguard Worker 257*795d594fSAndroid Build Coastguard Worker // Test discovery with MethodHandles.lookup() which is caller 258*795d594fSAndroid Build Coastguard Worker // context sensitive. 259*795d594fSAndroid Build Coastguard Worker 260*795d594fSAndroid Build Coastguard Worker final MethodHandles.Lookup lookup = MethodHandles.lookup(); 261*795d594fSAndroid Build Coastguard Worker if (JLI.canDiscoverWithLookupFindGetter(lookup, klass, name, int.class) 262*795d594fSAndroid Build Coastguard Worker != canDiscover) { 263*795d594fSAndroid Build Coastguard Worker throwDiscoveryException(klass, name, true, "MethodHandles.lookup().findGetter()", 264*795d594fSAndroid Build Coastguard Worker canDiscover); 265*795d594fSAndroid Build Coastguard Worker } 266*795d594fSAndroid Build Coastguard Worker if (JLI.canDiscoverWithLookupFindStaticGetter(lookup, klass, name, int.class) 267*795d594fSAndroid Build Coastguard Worker != canDiscover) { 268*795d594fSAndroid Build Coastguard Worker throwDiscoveryException(klass, name, true, "MethodHandles.lookup().findStaticGetter()", 269*795d594fSAndroid Build Coastguard Worker canDiscover); 270*795d594fSAndroid Build Coastguard Worker } 271*795d594fSAndroid Build Coastguard Worker 272*795d594fSAndroid Build Coastguard Worker // Test discovery with MethodHandles.publicLookup() which can only 273*795d594fSAndroid Build Coastguard Worker // see public fields. Looking up setters here and fields in 274*795d594fSAndroid Build Coastguard Worker // interfaces are implicitly final. 275*795d594fSAndroid Build Coastguard Worker 276*795d594fSAndroid Build Coastguard Worker final MethodHandles.Lookup publicLookup = MethodHandles.publicLookup(); 277*795d594fSAndroid Build Coastguard Worker if (JLI.canDiscoverWithLookupFindSetter(publicLookup, klass, name, int.class) 278*795d594fSAndroid Build Coastguard Worker != canDiscover) { 279*795d594fSAndroid Build Coastguard Worker throwDiscoveryException(klass, name, true, "MethodHandles.publicLookup().findSetter()", 280*795d594fSAndroid Build Coastguard Worker canDiscover); 281*795d594fSAndroid Build Coastguard Worker } 282*795d594fSAndroid Build Coastguard Worker if (JLI.canDiscoverWithLookupFindStaticSetter(publicLookup, klass, name, int.class) 283*795d594fSAndroid Build Coastguard Worker != canDiscover) { 284*795d594fSAndroid Build Coastguard Worker throwDiscoveryException(klass, name, true, "MethodHandles.publicLookup().findStaticSetter()", 285*795d594fSAndroid Build Coastguard Worker canDiscover); 286*795d594fSAndroid Build Coastguard Worker } 287*795d594fSAndroid Build Coastguard Worker 288*795d594fSAndroid Build Coastguard Worker // Check for meta reflection. 289*795d594fSAndroid Build Coastguard Worker 290*795d594fSAndroid Build Coastguard Worker // With hidden api check hardening enabled, only white and light greylisted fields should be 291*795d594fSAndroid Build Coastguard Worker // discoverable. 292*795d594fSAndroid Build Coastguard Worker if (Reflection.canDiscoverFieldWithMetaReflection(klass, name, true) != canDiscover) { 293*795d594fSAndroid Build Coastguard Worker throwDiscoveryException(klass, name, false, 294*795d594fSAndroid Build Coastguard Worker "Meta reflection with hidden api hardening enabled", canDiscover); 295*795d594fSAndroid Build Coastguard Worker } 296*795d594fSAndroid Build Coastguard Worker 297*795d594fSAndroid Build Coastguard Worker if (testHiddenApiCheckHardeningDisabled) { 298*795d594fSAndroid Build Coastguard Worker // With hidden api check hardening disabled, all fields should be discoverable. 299*795d594fSAndroid Build Coastguard Worker if (Reflection.canDiscoverFieldWithMetaReflection(klass, name, false) != true) { 300*795d594fSAndroid Build Coastguard Worker throwDiscoveryException(klass, name, false, 301*795d594fSAndroid Build Coastguard Worker "Meta reflection with hidden api hardening enabled", canDiscover); 302*795d594fSAndroid Build Coastguard Worker } 303*795d594fSAndroid Build Coastguard Worker } 304*795d594fSAndroid Build Coastguard Worker 305*795d594fSAndroid Build Coastguard Worker if (canDiscover) { 306*795d594fSAndroid Build Coastguard Worker // Test that modifiers are unaffected. 307*795d594fSAndroid Build Coastguard Worker 308*795d594fSAndroid Build Coastguard Worker if (Reflection.canObserveFieldHiddenAccessFlags(klass, name)) { 309*795d594fSAndroid Build Coastguard Worker throwModifiersException(klass, name, true); 310*795d594fSAndroid Build Coastguard Worker } 311*795d594fSAndroid Build Coastguard Worker 312*795d594fSAndroid Build Coastguard Worker // Test getters and setters when meaningful. 313*795d594fSAndroid Build Coastguard Worker 314*795d594fSAndroid Build Coastguard Worker if (!Reflection.canGetField(klass, name)) { 315*795d594fSAndroid Build Coastguard Worker throwAccessException(klass, name, true, "Field.getInt()"); 316*795d594fSAndroid Build Coastguard Worker } 317*795d594fSAndroid Build Coastguard Worker if (!Reflection.canSetField(klass, name)) { 318*795d594fSAndroid Build Coastguard Worker throwAccessException(klass, name, true, "Field.setInt()"); 319*795d594fSAndroid Build Coastguard Worker } 320*795d594fSAndroid Build Coastguard Worker if (!JNI.canGetField(klass, name, isStatic)) { 321*795d594fSAndroid Build Coastguard Worker throwAccessException(klass, name, true, "getIntField"); 322*795d594fSAndroid Build Coastguard Worker } 323*795d594fSAndroid Build Coastguard Worker if (!JNI.canSetField(klass, name, isStatic)) { 324*795d594fSAndroid Build Coastguard Worker throwAccessException(klass, name, true, "setIntField"); 325*795d594fSAndroid Build Coastguard Worker } 326*795d594fSAndroid Build Coastguard Worker } 327*795d594fSAndroid Build Coastguard Worker 328*795d594fSAndroid Build Coastguard Worker // Test that callbacks are invoked correctly. 329*795d594fSAndroid Build Coastguard Worker checkMemberCallback(klass, name, isPublic, true /* isField */, invokesMemberCallback); 330*795d594fSAndroid Build Coastguard Worker } 331*795d594fSAndroid Build Coastguard Worker checkMethod(Class<?> klass, String name, boolean isStatic, Visibility visibility, Behaviour behaviour, boolean invokesMemberCallback, boolean testHiddenApiCheckHardeningDisabled)332*795d594fSAndroid Build Coastguard Worker private static void checkMethod(Class<?> klass, String name, boolean isStatic, 333*795d594fSAndroid Build Coastguard Worker Visibility visibility, Behaviour behaviour, boolean invokesMemberCallback, 334*795d594fSAndroid Build Coastguard Worker boolean testHiddenApiCheckHardeningDisabled) throws Exception { 335*795d594fSAndroid Build Coastguard Worker 336*795d594fSAndroid Build Coastguard Worker boolean isPublic = (visibility == Visibility.Public); 337*795d594fSAndroid Build Coastguard Worker if (klass.isInterface() && !isPublic) { 338*795d594fSAndroid Build Coastguard Worker // All interface members are public. 339*795d594fSAndroid Build Coastguard Worker return; 340*795d594fSAndroid Build Coastguard Worker } 341*795d594fSAndroid Build Coastguard Worker 342*795d594fSAndroid Build Coastguard Worker boolean canDiscover = (behaviour != Behaviour.Denied); 343*795d594fSAndroid Build Coastguard Worker 344*795d594fSAndroid Build Coastguard Worker // Test discovery with reflection. 345*795d594fSAndroid Build Coastguard Worker 346*795d594fSAndroid Build Coastguard Worker if (Reflection.canDiscoverWithGetDeclaredMethod(klass, name) != canDiscover) { 347*795d594fSAndroid Build Coastguard Worker throwDiscoveryException(klass, name, false, "getDeclaredMethod()", canDiscover); 348*795d594fSAndroid Build Coastguard Worker } 349*795d594fSAndroid Build Coastguard Worker 350*795d594fSAndroid Build Coastguard Worker if (Reflection.canDiscoverWithGetDeclaredMethods(klass, name) != canDiscover) { 351*795d594fSAndroid Build Coastguard Worker throwDiscoveryException(klass, name, false, "getDeclaredMethods()", canDiscover); 352*795d594fSAndroid Build Coastguard Worker } 353*795d594fSAndroid Build Coastguard Worker 354*795d594fSAndroid Build Coastguard Worker if (Reflection.canDiscoverWithGetMethod(klass, name) != (canDiscover && isPublic)) { 355*795d594fSAndroid Build Coastguard Worker throwDiscoveryException(klass, name, false, "getMethod()", (canDiscover && isPublic)); 356*795d594fSAndroid Build Coastguard Worker } 357*795d594fSAndroid Build Coastguard Worker 358*795d594fSAndroid Build Coastguard Worker if (Reflection.canDiscoverWithGetMethods(klass, name) != (canDiscover && isPublic)) { 359*795d594fSAndroid Build Coastguard Worker throwDiscoveryException(klass, name, false, "getMethods()", (canDiscover && isPublic)); 360*795d594fSAndroid Build Coastguard Worker } 361*795d594fSAndroid Build Coastguard Worker 362*795d594fSAndroid Build Coastguard Worker // Test discovery with JNI. 363*795d594fSAndroid Build Coastguard Worker 364*795d594fSAndroid Build Coastguard Worker if (JNI.canDiscoverMethod(klass, name, isStatic) != canDiscover) { 365*795d594fSAndroid Build Coastguard Worker throwDiscoveryException(klass, name, false, "JNI", canDiscover); 366*795d594fSAndroid Build Coastguard Worker } 367*795d594fSAndroid Build Coastguard Worker 368*795d594fSAndroid Build Coastguard Worker // Test discovery with MethodHandles.lookup(). 369*795d594fSAndroid Build Coastguard Worker 370*795d594fSAndroid Build Coastguard Worker final MethodHandles.Lookup lookup = MethodHandles.lookup(); 371*795d594fSAndroid Build Coastguard Worker final MethodType methodType = MethodType.methodType(int.class); 372*795d594fSAndroid Build Coastguard Worker if (JLI.canDiscoverWithLookupFindVirtual(lookup, klass, name, methodType) != canDiscover) { 373*795d594fSAndroid Build Coastguard Worker throwDiscoveryException(klass, name, false, "MethodHandles.lookup().findVirtual()", 374*795d594fSAndroid Build Coastguard Worker canDiscover); 375*795d594fSAndroid Build Coastguard Worker } 376*795d594fSAndroid Build Coastguard Worker 377*795d594fSAndroid Build Coastguard Worker if (JLI.canDiscoverWithLookupFindStatic(lookup, klass, name, methodType) != canDiscover) { 378*795d594fSAndroid Build Coastguard Worker throwDiscoveryException(klass, name, false, "MethodHandles.lookup().findStatic()", 379*795d594fSAndroid Build Coastguard Worker canDiscover); 380*795d594fSAndroid Build Coastguard Worker } 381*795d594fSAndroid Build Coastguard Worker 382*795d594fSAndroid Build Coastguard Worker // Check for meta reflection. 383*795d594fSAndroid Build Coastguard Worker 384*795d594fSAndroid Build Coastguard Worker // With hidden api check hardening enabled, only white and light greylisted methods should be 385*795d594fSAndroid Build Coastguard Worker // discoverable. 386*795d594fSAndroid Build Coastguard Worker if (Reflection.canDiscoverMethodWithMetaReflection(klass, name, true) != canDiscover) { 387*795d594fSAndroid Build Coastguard Worker throwDiscoveryException(klass, name, false, 388*795d594fSAndroid Build Coastguard Worker "Meta reflection with hidden api hardening enabled", canDiscover); 389*795d594fSAndroid Build Coastguard Worker } 390*795d594fSAndroid Build Coastguard Worker 391*795d594fSAndroid Build Coastguard Worker if (testHiddenApiCheckHardeningDisabled) { 392*795d594fSAndroid Build Coastguard Worker // With hidden api check hardening disabled, all methods should be discoverable. 393*795d594fSAndroid Build Coastguard Worker if (Reflection.canDiscoverMethodWithMetaReflection(klass, name, false) != true) { 394*795d594fSAndroid Build Coastguard Worker throwDiscoveryException(klass, name, false, 395*795d594fSAndroid Build Coastguard Worker "Meta reflection with hidden api hardening enabled", canDiscover); 396*795d594fSAndroid Build Coastguard Worker } 397*795d594fSAndroid Build Coastguard Worker } 398*795d594fSAndroid Build Coastguard Worker 399*795d594fSAndroid Build Coastguard Worker // Finish here if we could not discover the method. 400*795d594fSAndroid Build Coastguard Worker 401*795d594fSAndroid Build Coastguard Worker if (canDiscover) { 402*795d594fSAndroid Build Coastguard Worker // Test that modifiers are unaffected. 403*795d594fSAndroid Build Coastguard Worker 404*795d594fSAndroid Build Coastguard Worker if (Reflection.canObserveMethodHiddenAccessFlags(klass, name)) { 405*795d594fSAndroid Build Coastguard Worker throwModifiersException(klass, name, false); 406*795d594fSAndroid Build Coastguard Worker } 407*795d594fSAndroid Build Coastguard Worker 408*795d594fSAndroid Build Coastguard Worker // Test whether we can invoke the method. This skips non-static interface methods. 409*795d594fSAndroid Build Coastguard Worker if (!klass.isInterface() || isStatic) { 410*795d594fSAndroid Build Coastguard Worker if (!Reflection.canInvokeMethod(klass, name)) { 411*795d594fSAndroid Build Coastguard Worker throwAccessException(klass, name, false, "invoke()"); 412*795d594fSAndroid Build Coastguard Worker } 413*795d594fSAndroid Build Coastguard Worker if (!JNI.canInvokeMethodA(klass, name, isStatic)) { 414*795d594fSAndroid Build Coastguard Worker throwAccessException(klass, name, false, "CallMethodA"); 415*795d594fSAndroid Build Coastguard Worker } 416*795d594fSAndroid Build Coastguard Worker if (!JNI.canInvokeMethodV(klass, name, isStatic)) { 417*795d594fSAndroid Build Coastguard Worker throwAccessException(klass, name, false, "CallMethodV"); 418*795d594fSAndroid Build Coastguard Worker } 419*795d594fSAndroid Build Coastguard Worker } 420*795d594fSAndroid Build Coastguard Worker } 421*795d594fSAndroid Build Coastguard Worker 422*795d594fSAndroid Build Coastguard Worker // Test that callbacks are invoked correctly. 423*795d594fSAndroid Build Coastguard Worker checkMemberCallback(klass, name, isPublic, false /* isField */, invokesMemberCallback); 424*795d594fSAndroid Build Coastguard Worker } 425*795d594fSAndroid Build Coastguard Worker checkConstructor(Class<?> klass, Visibility visibility, Hiddenness hiddenness, Behaviour behaviour, boolean testHiddenApiCheckHardeningDisabled)426*795d594fSAndroid Build Coastguard Worker private static void checkConstructor(Class<?> klass, Visibility visibility, Hiddenness hiddenness, 427*795d594fSAndroid Build Coastguard Worker Behaviour behaviour, boolean testHiddenApiCheckHardeningDisabled) throws Exception { 428*795d594fSAndroid Build Coastguard Worker 429*795d594fSAndroid Build Coastguard Worker boolean isPublic = (visibility == Visibility.Public); 430*795d594fSAndroid Build Coastguard Worker String signature = "(" + visibility.mAssociatedType.mShorty + 431*795d594fSAndroid Build Coastguard Worker hiddenness.mAssociatedType.mShorty + ")V"; 432*795d594fSAndroid Build Coastguard Worker String fullName = "<init>" + signature; 433*795d594fSAndroid Build Coastguard Worker Class<?> args[] = new Class[] { visibility.mAssociatedType.mClass, 434*795d594fSAndroid Build Coastguard Worker hiddenness.mAssociatedType.mClass }; 435*795d594fSAndroid Build Coastguard Worker Object initargs[] = new Object[] { visibility.mAssociatedType.mDefaultValue, 436*795d594fSAndroid Build Coastguard Worker hiddenness.mAssociatedType.mDefaultValue }; 437*795d594fSAndroid Build Coastguard Worker MethodType methodType = MethodType.methodType(void.class, args); 438*795d594fSAndroid Build Coastguard Worker 439*795d594fSAndroid Build Coastguard Worker boolean canDiscover = (behaviour != Behaviour.Denied); 440*795d594fSAndroid Build Coastguard Worker 441*795d594fSAndroid Build Coastguard Worker // Test discovery with reflection. 442*795d594fSAndroid Build Coastguard Worker 443*795d594fSAndroid Build Coastguard Worker if (Reflection.canDiscoverWithGetDeclaredConstructor(klass, args) != canDiscover) { 444*795d594fSAndroid Build Coastguard Worker throwDiscoveryException(klass, fullName, false, "getDeclaredConstructor()", canDiscover); 445*795d594fSAndroid Build Coastguard Worker } 446*795d594fSAndroid Build Coastguard Worker 447*795d594fSAndroid Build Coastguard Worker if (Reflection.canDiscoverWithGetDeclaredConstructors(klass, args) != canDiscover) { 448*795d594fSAndroid Build Coastguard Worker throwDiscoveryException(klass, fullName, false, "getDeclaredConstructors()", canDiscover); 449*795d594fSAndroid Build Coastguard Worker } 450*795d594fSAndroid Build Coastguard Worker 451*795d594fSAndroid Build Coastguard Worker if (Reflection.canDiscoverWithGetConstructor(klass, args) != (canDiscover && isPublic)) { 452*795d594fSAndroid Build Coastguard Worker throwDiscoveryException( 453*795d594fSAndroid Build Coastguard Worker klass, fullName, false, "getConstructor()", (canDiscover && isPublic)); 454*795d594fSAndroid Build Coastguard Worker } 455*795d594fSAndroid Build Coastguard Worker 456*795d594fSAndroid Build Coastguard Worker if (Reflection.canDiscoverWithGetConstructors(klass, args) != (canDiscover && isPublic)) { 457*795d594fSAndroid Build Coastguard Worker throwDiscoveryException( 458*795d594fSAndroid Build Coastguard Worker klass, fullName, false, "getConstructors()", (canDiscover && isPublic)); 459*795d594fSAndroid Build Coastguard Worker } 460*795d594fSAndroid Build Coastguard Worker 461*795d594fSAndroid Build Coastguard Worker // Test discovery with JNI. 462*795d594fSAndroid Build Coastguard Worker 463*795d594fSAndroid Build Coastguard Worker if (JNI.canDiscoverConstructor(klass, signature) != canDiscover) { 464*795d594fSAndroid Build Coastguard Worker throwDiscoveryException(klass, fullName, false, "JNI", canDiscover); 465*795d594fSAndroid Build Coastguard Worker } 466*795d594fSAndroid Build Coastguard Worker 467*795d594fSAndroid Build Coastguard Worker // Test discovery with MethodHandles.lookup() 468*795d594fSAndroid Build Coastguard Worker 469*795d594fSAndroid Build Coastguard Worker final MethodHandles.Lookup lookup = MethodHandles.lookup(); 470*795d594fSAndroid Build Coastguard Worker if (JLI.canDiscoverWithLookupFindConstructor(lookup, klass, methodType) != canDiscover) { 471*795d594fSAndroid Build Coastguard Worker throwDiscoveryException(klass, fullName, false, "MethodHandles.lookup().findConstructor", 472*795d594fSAndroid Build Coastguard Worker canDiscover); 473*795d594fSAndroid Build Coastguard Worker } 474*795d594fSAndroid Build Coastguard Worker 475*795d594fSAndroid Build Coastguard Worker final MethodHandles.Lookup publicLookup = MethodHandles.publicLookup(); 476*795d594fSAndroid Build Coastguard Worker if (JLI.canDiscoverWithLookupFindConstructor(publicLookup, klass, methodType) != canDiscover) { 477*795d594fSAndroid Build Coastguard Worker throwDiscoveryException(klass, fullName, false, 478*795d594fSAndroid Build Coastguard Worker "MethodHandles.publicLookup().findConstructor", 479*795d594fSAndroid Build Coastguard Worker canDiscover); 480*795d594fSAndroid Build Coastguard Worker } 481*795d594fSAndroid Build Coastguard Worker 482*795d594fSAndroid Build Coastguard Worker // Check for meta reflection. 483*795d594fSAndroid Build Coastguard Worker 484*795d594fSAndroid Build Coastguard Worker // With hidden api check hardening enabled, only white and light greylisted constructors should 485*795d594fSAndroid Build Coastguard Worker // be discoverable. 486*795d594fSAndroid Build Coastguard Worker if (Reflection.canDiscoverConstructorWithMetaReflection(klass, args, true) != canDiscover) { 487*795d594fSAndroid Build Coastguard Worker throwDiscoveryException(klass, fullName, false, 488*795d594fSAndroid Build Coastguard Worker "Meta reflection with hidden api hardening enabled", canDiscover); 489*795d594fSAndroid Build Coastguard Worker } 490*795d594fSAndroid Build Coastguard Worker 491*795d594fSAndroid Build Coastguard Worker if (testHiddenApiCheckHardeningDisabled) { 492*795d594fSAndroid Build Coastguard Worker // With hidden api check hardening disabled, all constructors should be discoverable. 493*795d594fSAndroid Build Coastguard Worker if (Reflection.canDiscoverConstructorWithMetaReflection(klass, args, false) != true) { 494*795d594fSAndroid Build Coastguard Worker throwDiscoveryException(klass, fullName, false, 495*795d594fSAndroid Build Coastguard Worker "Meta reflection with hidden api hardening enabled", canDiscover); 496*795d594fSAndroid Build Coastguard Worker } 497*795d594fSAndroid Build Coastguard Worker } 498*795d594fSAndroid Build Coastguard Worker 499*795d594fSAndroid Build Coastguard Worker if (canDiscover) { 500*795d594fSAndroid Build Coastguard Worker // Test whether we can invoke the constructor. 501*795d594fSAndroid Build Coastguard Worker 502*795d594fSAndroid Build Coastguard Worker if (!Reflection.canInvokeConstructor(klass, args, initargs)) { 503*795d594fSAndroid Build Coastguard Worker throwAccessException(klass, fullName, false, "invoke()"); 504*795d594fSAndroid Build Coastguard Worker } 505*795d594fSAndroid Build Coastguard Worker if (!JNI.canInvokeConstructorA(klass, signature)) { 506*795d594fSAndroid Build Coastguard Worker throwAccessException(klass, fullName, false, "NewObjectA"); 507*795d594fSAndroid Build Coastguard Worker } 508*795d594fSAndroid Build Coastguard Worker if (!JNI.canInvokeConstructorV(klass, signature)) { 509*795d594fSAndroid Build Coastguard Worker throwAccessException(klass, fullName, false, "NewObjectV"); 510*795d594fSAndroid Build Coastguard Worker } 511*795d594fSAndroid Build Coastguard Worker } 512*795d594fSAndroid Build Coastguard Worker } 513*795d594fSAndroid Build Coastguard Worker checkNullaryConstructor(Class<?> klass, Behaviour behaviour)514*795d594fSAndroid Build Coastguard Worker private static void checkNullaryConstructor(Class<?> klass, Behaviour behaviour) 515*795d594fSAndroid Build Coastguard Worker throws Exception { 516*795d594fSAndroid Build Coastguard Worker boolean canAccess = (behaviour != Behaviour.Denied); 517*795d594fSAndroid Build Coastguard Worker 518*795d594fSAndroid Build Coastguard Worker if (Reflection.canUseNewInstance(klass) != canAccess) { 519*795d594fSAndroid Build Coastguard Worker throw new RuntimeException("Expected to " + (canAccess ? "" : "not ") + 520*795d594fSAndroid Build Coastguard Worker "be able to construct " + klass.getName() + ". " + configMessage); 521*795d594fSAndroid Build Coastguard Worker } 522*795d594fSAndroid Build Coastguard Worker } 523*795d594fSAndroid Build Coastguard Worker checkLinking(String className, boolean takesParameter, Behaviour behaviour)524*795d594fSAndroid Build Coastguard Worker private static void checkLinking(String className, boolean takesParameter, Behaviour behaviour) 525*795d594fSAndroid Build Coastguard Worker throws Exception { 526*795d594fSAndroid Build Coastguard Worker boolean canAccess = (behaviour != Behaviour.Denied); 527*795d594fSAndroid Build Coastguard Worker 528*795d594fSAndroid Build Coastguard Worker if (Linking.canAccess(className, takesParameter) != canAccess) { 529*795d594fSAndroid Build Coastguard Worker throw new RuntimeException("Expected to " + (canAccess ? "" : "not ") + 530*795d594fSAndroid Build Coastguard Worker "be able to verify " + className + "." + configMessage); 531*795d594fSAndroid Build Coastguard Worker } 532*795d594fSAndroid Build Coastguard Worker } 533*795d594fSAndroid Build Coastguard Worker throwDiscoveryException(Class<?> klass, String name, boolean isField, String fn, boolean canAccess)534*795d594fSAndroid Build Coastguard Worker private static void throwDiscoveryException(Class<?> klass, String name, boolean isField, 535*795d594fSAndroid Build Coastguard Worker String fn, boolean canAccess) { 536*795d594fSAndroid Build Coastguard Worker throw new RuntimeException("Expected " + (isField ? "field " : "method ") + klass.getName() + 537*795d594fSAndroid Build Coastguard Worker "." + name + " to " + (canAccess ? "" : "not ") + "be discoverable with " + fn + ". " + 538*795d594fSAndroid Build Coastguard Worker configMessage); 539*795d594fSAndroid Build Coastguard Worker } 540*795d594fSAndroid Build Coastguard Worker throwAccessException(Class<?> klass, String name, boolean isField, String fn)541*795d594fSAndroid Build Coastguard Worker private static void throwAccessException(Class<?> klass, String name, boolean isField, 542*795d594fSAndroid Build Coastguard Worker String fn) { 543*795d594fSAndroid Build Coastguard Worker throw new RuntimeException("Expected to be able to access " + (isField ? "field " : "method ") + 544*795d594fSAndroid Build Coastguard Worker klass.getName() + "." + name + " using " + fn + ". " + configMessage); 545*795d594fSAndroid Build Coastguard Worker } 546*795d594fSAndroid Build Coastguard Worker throwModifiersException(Class<?> klass, String name, boolean isField)547*795d594fSAndroid Build Coastguard Worker private static void throwModifiersException(Class<?> klass, String name, boolean isField) { 548*795d594fSAndroid Build Coastguard Worker throw new RuntimeException("Expected " + (isField ? "field " : "method ") + klass.getName() + 549*795d594fSAndroid Build Coastguard Worker "." + name + " to not expose hidden modifiers"); 550*795d594fSAndroid Build Coastguard Worker } 551*795d594fSAndroid Build Coastguard Worker 552*795d594fSAndroid Build Coastguard Worker private static DexDomain parentDomain; 553*795d594fSAndroid Build Coastguard Worker private static DexDomain childDomain; 554*795d594fSAndroid Build Coastguard Worker private static boolean everythingSdked; 555*795d594fSAndroid Build Coastguard Worker 556*795d594fSAndroid Build Coastguard Worker private static String configMessage; 557*795d594fSAndroid Build Coastguard Worker } 558