// checkNativeOnly: Only run tests where the caller is in native code - this ChildClass object // is in the core-platform domain when it is true. publicstaticvoid runTest(String libFileName, int parentDomainOrdinal, int childDomainOrdinal, boolean everythingSdked, boolean checkNativeOnly) throws Exception {
System.load(libFileName);
boolean skipJniTests = false; if (childDomain == DexDomain.Application) {
registerAppJniApiCallers(JNI.class);
} elseif (childDomain == DexDomain.CorePlatform) {
registerCorePlatformJniApiCallers(JNI.class);
} else { // It's difficult to put a .so in a location that identifies it as the platform domain, so // skip those JNI tests.
skipJniTests = true;
}
int targetSdkVersion = VMRuntime.getRuntime().getTargetSdkVersion(); if (checkNativeOnly) { if (targetSdkVersion != 10000) { thrownew RuntimeException( "Expected future targetSdkVersion for native caller tests, got " + targetSdkVersion);
}
}
// Check expectations about loading into boot class path. boolean isParentInBoot = (ParentClass.class.getClassLoader().getParent() == null); boolean expectedParentInBoot = (parentDomain != DexDomain.Application); if (isParentInBoot != expectedParentInBoot) { thrownew RuntimeException("Expected ParentClass " +
(expectedParentInBoot ? "" : "not ") + "in boot class path");
} boolean isChildInBoot = (ChildClass.class.getClassLoader().getParent() == null); boolean expectedChildInBoot = (childDomain != DexDomain.Application); if (isChildInBoot != expectedChildInBoot && !checkNativeOnly) { thrownew RuntimeException("Expected ChildClass " + (expectedChildInBoot ? "" : "not ") + "in boot class path");
}
// For compat reasons, meta-reflection should still be usable by apps if hidden api check // hardening is disabled (i.e. target SDK is Q or earlier). The only configuration where this // workaround used to work is for ChildClass in the Application domain and ParentClass in the // Platform domain, so only test that configuration with hidden api check hardening disabled. boolean testHiddenApiCheckHardeningDisabled =
(childDomain == DexDomain.Application) && (parentDomain == DexDomain.Platform);
// Run meaningful combinations of access flags. for (Hiddenness hiddenness : Hiddenness.values()) { final Behaviour expected; finalboolean invokesMemberCallback; // Warnings are now disabled whenever access is granted, even for // greylisted APIs. This is the behaviour for release builds. if (everythingSdked || hiddenness == Hiddenness.Sdk) {
expected = Behaviour.Granted;
invokesMemberCallback = false;
} elseif (parentDomain == DexDomain.CorePlatform && childDomain == DexDomain.Platform) {
expected = (hiddenness == Hiddenness.Unsupported
|| hiddenness == Hiddenness.BlocklistAndCorePlatformApi)
? Behaviour.Granted
: Behaviour.Denied;
invokesMemberCallback = false;
} elseif (isSameBoot) {
expected = Behaviour.Granted;
invokesMemberCallback = false;
} elseif (hiddenness == Hiddenness.Blocklist ||
hiddenness == Hiddenness.BlocklistAndCorePlatformApi) {
expected = Behaviour.Denied;
invokesMemberCallback = true;
} elseif (hiddenness == Hiddenness.ConditionallyBlocked && targetSdkVersion == 10000) {
expected = Behaviour.Denied;
invokesMemberCallback = true; // Not applicable when checkNativeOnly is true.
} else {
expected = Behaviour.Warning;
invokesMemberCallback = true;
}
// Saved variables from the loops below to be shown in the test context if an exception is // thrown. boolean saveIsStatic = false;
Visibility saveVisibility = Visibility.Public; Class saveParentClass = null;
// Check whether one can use a class constructor.
checkConstructor(ParentClass.class, visibility, hiddenness, expected,
testHiddenApiCheckHardeningDisabled, skipJniTests, checkNativeOnly);
// Check whether one can use an interface default method.
String name = "method" + visibility.name() + "Default" + hiddenness.name();
checkMethod(ParentInterface.class, name, /*isStatic*/ false, visibility, expected,
invokesMemberCallback, testHiddenApiCheckHardeningDisabled, skipJniTests,
checkNativeOnly);
}
// Test discovery with MethodHandles.publicLookup() which can only // see public fields. Looking up setters here and fields in // interfaces are implicitly final.
// With hidden api check hardening enabled, only white and light greylisted fields should be // discoverable. if (Reflection.canDiscoverFieldWithMetaReflection(klass, name, true) != canDiscover) {
throwDiscoveryException(
klass, name, false, "Meta reflection with hidden api hardening enabled", canDiscover);
}
if (testHiddenApiCheckHardeningDisabled) { // With hidden api check hardening disabled, all fields should be discoverable. if (Reflection.canDiscoverFieldWithMetaReflection(klass, name, false) != true) {
throwDiscoveryException(
klass, name, false, "Meta reflection with hidden api hardening enabled", canDiscover);
}
}
}
if (canDiscover) { if (!checkNativeOnly) { // Test that modifiers are unaffected.
if (Reflection.canObserveFieldHiddenAccessFlags(klass, name)) {
throwModifiersException(klass, name, true);
}
if (!skipJniTests) { if (!JNI.canGetField(klass, name, isStatic)) {
throwAccessException(klass, name, true, "getIntField");
} if (!isUnmodifiable(klass, name) && !JNI.canSetField(klass, name, isStatic)) {
throwAccessException(klass, name, true, "setIntField");
}
}
}
// Test that callbacks are invoked correctly. if (!checkNativeOnly) {
checkMemberCallback(klass, name, isPublic, true/* isField */, invokesMemberCallback);
}
}
privatestaticfinalboolean isUnmodifiable(Class<?> klass, String fieldName) throws Exception {
Field field = klass.getDeclaredField(fieldName);
// With hidden api check hardening enabled, only white and light greylisted methods should be // discoverable. if (Reflection.canDiscoverMethodWithMetaReflection(klass, name, true) != canDiscover) {
throwDiscoveryException(
klass, name, false, "Meta reflection with hidden api hardening enabled", canDiscover);
}
if (testHiddenApiCheckHardeningDisabled) { // With hidden api check hardening disabled, all methods should be discoverable. if (Reflection.canDiscoverMethodWithMetaReflection(klass, name, false) != true) {
throwDiscoveryException(
klass, name, false, "Meta reflection with hidden api hardening enabled", canDiscover);
}
}
}
// Finish here if we could not discover the method.
if (canDiscover) { // Test that modifiers are unaffected.
if (!checkNativeOnly && Reflection.canObserveMethodHiddenAccessFlags(klass, name)) {
throwModifiersException(klass, name, false);
}
// Test whether we can invoke the method. This skips non-static interface methods. if (!klass.isInterface() || isStatic) { if (!checkNativeOnly && !Reflection.canInvokeMethod(klass, name)) {
throwAccessException(klass, name, false, "invoke()");
} if (!skipJniTests) { if (!JNI.canInvokeMethodA(klass, name, isStatic)) {
throwAccessException(klass, name, false, "CallMethodA");
} if (!JNI.canInvokeMethodV(klass, name, isStatic)) {
throwAccessException(klass, name, false, "CallMethodV");
}
}
}
}
// Test that callbacks are invoked correctly. if (!checkNativeOnly) {
checkMemberCallback(klass, name, isPublic, false/* isField */, invokesMemberCallback);
}
}
final MethodHandles.Lookup lookup = MethodHandles.lookup(); if (JLI.canDiscoverWithLookupFindConstructor(lookup, klass, methodType) != canDiscover) {
throwDiscoveryException(
klass, fullName, false, "MethodHandles.lookup().findConstructor", canDiscover);
}
final MethodHandles.Lookup publicLookup = MethodHandles.publicLookup(); if (JLI.canDiscoverWithLookupFindConstructor(publicLookup, klass, methodType)
!= canDiscover) {
throwDiscoveryException(
klass, fullName, false, "MethodHandles.publicLookup().findConstructor", canDiscover);
}
// Check for meta reflection.
// With hidden api check hardening enabled, only white and light greylisted constructors // should be discoverable. if (Reflection.canDiscoverConstructorWithMetaReflection(klass, args, true) != canDiscover) {
throwDiscoveryException(klass, fullName, false, "Meta reflection with hidden api hardening enabled", canDiscover);
}
if (testHiddenApiCheckHardeningDisabled) { // With hidden api check hardening disabled, all constructors should be discoverable. if (Reflection.canDiscoverConstructorWithMetaReflection(klass, args, false) != true) {
throwDiscoveryException(klass, fullName, false, "Meta reflection with hidden api hardening enabled", canDiscover);
}
}
}
if (canDiscover) { // Test whether we can invoke the constructor.
if (!checkNativeOnly && !Reflection.canInvokeConstructor(klass, args, initargs)) {
throwAccessException(klass, fullName, false, "invoke()");
} if (!skipJniTests) { if (!JNI.canInvokeConstructorA(klass, signature)) {
throwAccessException(klass, fullName, false, "NewObjectA");
} if (!JNI.canInvokeConstructorV(klass, signature)) {
throwAccessException(klass, fullName, false, "NewObjectV");
}
}
}
}
// Check a few real symbols that HiddenApiSdk28AppTest depends on being inaccessible from platform // to core-platform, to avoid false negatives. Only called when ChildClass is in the platform // domain. publicstaticvoid checkNonCorePlatformApis() { try {
Field f = Byte.class.getDeclaredField("value"); thrownew RuntimeException("Expected java.lang.Byte.value to be inaccessible from platform");
} catch (NoSuchFieldException expected) {
} try {
Method m =
Unsafe.class.getDeclaredMethod("getAndAddInt", Object.class, Long.class, Integer.class); thrownew RuntimeException( "Expected sun.misc.Unsafe.getAndAddInt to be inaccessible from platform");
} catch (NoSuchMethodException expected) {
}
}
}
Messung V0.5 in Prozent
¤ Dauer der Verarbeitung: 0.13 Sekunden
(vorverarbeitet am 2026-06-29)
¤
Die Informationen auf dieser Webseite wurden
nach bestem Wissen sorgfältig zusammengestellt. Es wird jedoch weder Vollständigkeit, noch Richtigkeit,
noch Qualität der bereit gestellten Informationen zugesichert.
Bemerkung:
Die farbliche Syntaxdarstellung und die Messung sind noch experimentell.