diff options
| -rw-r--r-- | runtime/hidden_api.cc | 33 | ||||
| -rw-r--r-- | runtime/native/java_lang_Class.cc | 7 | ||||
| -rw-r--r-- | runtime/well_known_classes.cc | 6 | ||||
| -rw-r--r-- | runtime/well_known_classes.h | 3 | ||||
| -rw-r--r-- | test/674-hiddenapi/build | 11 | ||||
| -rw-r--r-- | test/674-hiddenapi/src-ex/ChildClass.java | 180 |
6 files changed, 81 insertions, 159 deletions
diff --git a/runtime/hidden_api.cc b/runtime/hidden_api.cc index aad3917f87..f0b36a090a 100644 --- a/runtime/hidden_api.cc +++ b/runtime/hidden_api.cc @@ -16,11 +16,7 @@ #include "hidden_api.h" -#include <nativehelper/scoped_local_ref.h> - #include "base/dumpable.h" -#include "thread-current-inl.h" -#include "well_known_classes.h" namespace art { namespace hiddenapi { @@ -140,35 +136,6 @@ bool ShouldBlockAccessToMemberImpl(T* member, Action action, AccessMethod access member_signature.WarnAboutAccess(access_method, HiddenApiAccessFlags::DecodeFromRuntime(member->GetAccessFlags())); - // We're now not in the boot classpath and have decided to warn, show - // a toast or deny access. Let strict mode know if a callback is set. - // - // For consistency of reasoning, we assume that a callback is never set - // when running unstarted with dex2oat. - if (access_method == kReflection && !runtime->IsAotCompiler()) { - ScopedObjectAccessUnchecked soa(Thread::Current()); - - ScopedLocalRef<jobject> consumer_object(soa.Env(), - soa.Env()->GetStaticObjectField( - WellKnownClasses::dalvik_system_VMRuntime, - WellKnownClasses::dalvik_system_VMRuntime_nonSdkApiUsageConsumer)); - // If the consumer is non-null, we call back to it to let it know that we - // have encountered an API that's in one of our lists. - if (consumer_object != nullptr) { - std::ostringstream member_signature_str; - member_signature.Dump(member_signature_str); - - ScopedLocalRef<jobject> signature_str( - soa.Env(), - soa.Env()->NewStringUTF(member_signature_str.str().c_str())); - - // Call through to Consumer.accept(String memberSignature); - soa.Env()->CallVoidMethod(consumer_object.get(), - WellKnownClasses::java_util_function_Consumer_accept, - signature_str.get()); - } - } - if (action == kDeny) { // Block access return true; diff --git a/runtime/native/java_lang_Class.cc b/runtime/native/java_lang_Class.cc index 1c17806b5e..ad05856eaf 100644 --- a/runtime/native/java_lang_Class.cc +++ b/runtime/native/java_lang_Class.cc @@ -535,19 +535,18 @@ static jobjectArray Class_getDeclaredConstructorsInternal( static jobject Class_getDeclaredMethodInternal(JNIEnv* env, jobject javaThis, jstring name, jobjectArray args) { ScopedFastNativeObjectAccess soa(env); - StackHandleScope<1> hs(soa.Self()); DCHECK_EQ(Runtime::Current()->GetClassLinker()->GetImagePointerSize(), kRuntimePointerSize); DCHECK(!Runtime::Current()->IsActiveTransaction()); - Handle<mirror::Method> result = hs.NewHandle( + ObjPtr<mirror::Method> result = mirror::Class::GetDeclaredMethodInternal<kRuntimePointerSize, false>( soa.Self(), DecodeClass(soa, javaThis), soa.Decode<mirror::String>(name), - soa.Decode<mirror::ObjectArray<mirror::Class>>(args))); + soa.Decode<mirror::ObjectArray<mirror::Class>>(args)); if (result == nullptr || ShouldBlockAccessToMember(result->GetArtMethod(), soa.Self())) { return nullptr; } - return soa.AddLocalReference<jobject>(result.Get()); + return soa.AddLocalReference<jobject>(result); } static jobjectArray Class_getDeclaredMethodsUnchecked(JNIEnv* env, jobject javaThis, diff --git a/runtime/well_known_classes.cc b/runtime/well_known_classes.cc index 742e713774..bf36ccf0fa 100644 --- a/runtime/well_known_classes.cc +++ b/runtime/well_known_classes.cc @@ -77,7 +77,6 @@ jclass WellKnownClasses::java_nio_ByteBuffer; jclass WellKnownClasses::java_nio_DirectByteBuffer; jclass WellKnownClasses::java_util_ArrayList; jclass WellKnownClasses::java_util_Collections; -jclass WellKnownClasses::java_util_function_Consumer; jclass WellKnownClasses::libcore_reflect_AnnotationFactory; jclass WellKnownClasses::libcore_reflect_AnnotationMember; jclass WellKnownClasses::libcore_util_EmptyArray; @@ -116,7 +115,6 @@ jmethodID WellKnownClasses::java_lang_Thread_run; jmethodID WellKnownClasses::java_lang_ThreadGroup_add; jmethodID WellKnownClasses::java_lang_ThreadGroup_removeThread; jmethodID WellKnownClasses::java_nio_DirectByteBuffer_init; -jmethodID WellKnownClasses::java_util_function_Consumer_accept; jmethodID WellKnownClasses::libcore_reflect_AnnotationFactory_createAnnotation; jmethodID WellKnownClasses::libcore_reflect_AnnotationMember_init; jmethodID WellKnownClasses::org_apache_harmony_dalvik_ddmc_DdmServer_broadcast; @@ -127,7 +125,6 @@ jfieldID WellKnownClasses::dalvik_system_DexFile_fileName; jfieldID WellKnownClasses::dalvik_system_BaseDexClassLoader_pathList; jfieldID WellKnownClasses::dalvik_system_DexPathList_dexElements; jfieldID WellKnownClasses::dalvik_system_DexPathList__Element_dexFile; -jfieldID WellKnownClasses::dalvik_system_VMRuntime_nonSdkApiUsageConsumer; jfieldID WellKnownClasses::java_lang_Thread_daemon; jfieldID WellKnownClasses::java_lang_Thread_group; jfieldID WellKnownClasses::java_lang_Thread_lock; @@ -352,7 +349,6 @@ void WellKnownClasses::Init(JNIEnv* env) { java_nio_DirectByteBuffer = CacheClass(env, "java/nio/DirectByteBuffer"); java_util_ArrayList = CacheClass(env, "java/util/ArrayList"); java_util_Collections = CacheClass(env, "java/util/Collections"); - java_util_function_Consumer = CacheClass(env, "java/util/function/Consumer"); libcore_reflect_AnnotationFactory = CacheClass(env, "libcore/reflect/AnnotationFactory"); libcore_reflect_AnnotationMember = CacheClass(env, "libcore/reflect/AnnotationMember"); libcore_util_EmptyArray = CacheClass(env, "libcore/util/EmptyArray"); @@ -383,7 +379,6 @@ void WellKnownClasses::Init(JNIEnv* env) { java_lang_ThreadGroup_add = CacheMethod(env, java_lang_ThreadGroup, false, "add", "(Ljava/lang/Thread;)V"); java_lang_ThreadGroup_removeThread = CacheMethod(env, java_lang_ThreadGroup, false, "threadTerminated", "(Ljava/lang/Thread;)V"); java_nio_DirectByteBuffer_init = CacheMethod(env, java_nio_DirectByteBuffer, false, "<init>", "(JI)V"); - java_util_function_Consumer_accept = CacheMethod(env, java_util_function_Consumer, false, "accept", "(Ljava/lang/Object;)V"); libcore_reflect_AnnotationFactory_createAnnotation = CacheMethod(env, libcore_reflect_AnnotationFactory, true, "createAnnotation", "(Ljava/lang/Class;[Llibcore/reflect/AnnotationMember;)Ljava/lang/annotation/Annotation;"); libcore_reflect_AnnotationMember_init = CacheMethod(env, libcore_reflect_AnnotationMember, false, "<init>", "(Ljava/lang/String;Ljava/lang/Object;Ljava/lang/Class;Ljava/lang/reflect/Method;)V"); org_apache_harmony_dalvik_ddmc_DdmServer_broadcast = CacheMethod(env, org_apache_harmony_dalvik_ddmc_DdmServer, true, "broadcast", "(I)V"); @@ -394,7 +389,6 @@ void WellKnownClasses::Init(JNIEnv* env) { dalvik_system_DexFile_fileName = CacheField(env, dalvik_system_DexFile, false, "mFileName", "Ljava/lang/String;"); dalvik_system_DexPathList_dexElements = CacheField(env, dalvik_system_DexPathList, false, "dexElements", "[Ldalvik/system/DexPathList$Element;"); dalvik_system_DexPathList__Element_dexFile = CacheField(env, dalvik_system_DexPathList__Element, false, "dexFile", "Ldalvik/system/DexFile;"); - dalvik_system_VMRuntime_nonSdkApiUsageConsumer = CacheField(env, dalvik_system_VMRuntime, true, "nonSdkApiUsageConsumer", "Ljava/util/function/Consumer;"); java_lang_Thread_daemon = CacheField(env, java_lang_Thread, false, "daemon", "Z"); java_lang_Thread_group = CacheField(env, java_lang_Thread, false, "group", "Ljava/lang/ThreadGroup;"); java_lang_Thread_lock = CacheField(env, java_lang_Thread, false, "lock", "Ljava/lang/Object;"); diff --git a/runtime/well_known_classes.h b/runtime/well_known_classes.h index 7b1a2943d2..d5d7033132 100644 --- a/runtime/well_known_classes.h +++ b/runtime/well_known_classes.h @@ -85,7 +85,6 @@ struct WellKnownClasses { static jclass java_lang_Throwable; static jclass java_util_ArrayList; static jclass java_util_Collections; - static jclass java_util_function_Consumer; static jclass java_nio_ByteBuffer; static jclass java_nio_DirectByteBuffer; static jclass libcore_reflect_AnnotationFactory; @@ -126,7 +125,6 @@ struct WellKnownClasses { static jmethodID java_lang_ThreadGroup_add; static jmethodID java_lang_ThreadGroup_removeThread; static jmethodID java_nio_DirectByteBuffer_init; - static jmethodID java_util_function_Consumer_accept; static jmethodID libcore_reflect_AnnotationFactory_createAnnotation; static jmethodID libcore_reflect_AnnotationMember_init; static jmethodID org_apache_harmony_dalvik_ddmc_DdmServer_broadcast; @@ -137,7 +135,6 @@ struct WellKnownClasses { static jfieldID dalvik_system_DexFile_fileName; static jfieldID dalvik_system_DexPathList_dexElements; static jfieldID dalvik_system_DexPathList__Element_dexFile; - static jfieldID dalvik_system_VMRuntime_nonSdkApiUsageConsumer; static jfieldID java_lang_reflect_Executable_artMethod; static jfieldID java_lang_reflect_Proxy_h; static jfieldID java_lang_Thread_daemon; diff --git a/test/674-hiddenapi/build b/test/674-hiddenapi/build index 330a6def29..9012e8fd13 100644 --- a/test/674-hiddenapi/build +++ b/test/674-hiddenapi/build @@ -16,6 +16,15 @@ set -e +# Special build logic to handle src-ex .java files which have code that only builds on RI. +custom_build_logic() { + [[ -d ignore.src-ex ]] && mv ignore.src-ex src-ex + # src-ex uses code that can only build on RI. + ${JAVAC} -source 1.8 -target 1.8 -sourcepath src-ex -sourcepath src -d classes-ex $(find src-ex -name '*.java') + # remove src-ex so that default-build doesn't try to build it. + [[ -d src-ex ]] && mv src-ex ignore.src-ex +} + # Build the jars twice. First with applying hiddenapi, creating a boot jar, then # a second time without to create a normal jar. We need to do this because we # want to load the jar once as an app module and once as a member of the boot @@ -24,6 +33,7 @@ set -e # class path dex files, so the boot jar loads fine in the latter case. export USE_HIDDENAPI=true +custom_build_logic ./default-build "$@" # Move the jar file into the resource folder to be bundled with the test. @@ -35,4 +45,5 @@ mv ${TEST_NAME}.jar res/boot.jar rm -rf classes* export USE_HIDDENAPI=false +custom_build_logic ./default-build "$@" diff --git a/test/674-hiddenapi/src-ex/ChildClass.java b/test/674-hiddenapi/src-ex/ChildClass.java index 822224c539..582e907ca3 100644 --- a/test/674-hiddenapi/src-ex/ChildClass.java +++ b/test/674-hiddenapi/src-ex/ChildClass.java @@ -14,7 +14,6 @@ * limitations under the License. */ -import dalvik.system.VMRuntime; import java.lang.annotation.Annotation; import java.lang.reflect.Constructor; import java.lang.reflect.Field; @@ -22,7 +21,11 @@ import java.lang.reflect.InvocationTargetException; import java.lang.reflect.Method; import java.util.Arrays; import java.util.List; -import java.util.function.Consumer; + +import javax.lang.model.element.AnnotationMirror; +import javax.lang.model.type.PrimitiveType; +import javax.lang.model.type.TypeKind; +import javax.lang.model.type.TypeVisitor; public class ChildClass { enum PrimitiveType { @@ -133,47 +136,6 @@ public class ChildClass { } } - static final class RecordingConsumer implements Consumer<String> { - public String recordedValue = null; - - @Override - public void accept(String value) { - recordedValue = value; - } - } - - private static void checkMemberCallback(Class<?> klass, String name, - boolean isPublic, boolean isField) { - try { - RecordingConsumer consumer = new RecordingConsumer(); - VMRuntime.setNonSdkApiUsageConsumer(consumer); - try { - if (isPublic) { - if (isField) { - klass.getField(name); - } else { - klass.getMethod(name); - } - } else { - if (isField) { - klass.getDeclaredField(name); - } else { - klass.getDeclaredMethod(name); - } - } - } catch (NoSuchFieldException|NoSuchMethodException ignored) { - // We're not concerned whether an exception is thrown or not - we're - // only interested in whether the callback is invoked. - } - - if (consumer.recordedValue == null || !consumer.recordedValue.contains(name)) { - throw new RuntimeException("No callback for member: " + name); - } - } finally { - VMRuntime.setNonSdkApiUsageConsumer(null); - } - } - private static void checkField(Class<?> klass, String name, boolean isStatic, Visibility visibility, Behaviour behaviour) throws Exception { @@ -212,52 +174,48 @@ public class ChildClass { // Finish here if we could not discover the field. - if (canDiscover) { - // Test that modifiers are unaffected. + if (!canDiscover) { + return; + } - if (Reflection.canObserveFieldHiddenAccessFlags(klass, name)) { - throwModifiersException(klass, name, true); - } + // Test that modifiers are unaffected. - // Test getters and setters when meaningful. + if (Reflection.canObserveFieldHiddenAccessFlags(klass, name)) { + throwModifiersException(klass, name, true); + } - clearWarning(); - if (!Reflection.canGetField(klass, name)) { - throwAccessException(klass, name, true, "Field.getInt()"); - } - if (hasPendingWarning() != setsWarning) { - throwWarningException(klass, name, true, "Field.getInt()", setsWarning); - } + // Test getters and setters when meaningful. - clearWarning(); - if (!Reflection.canSetField(klass, name)) { - throwAccessException(klass, name, true, "Field.setInt()"); - } - if (hasPendingWarning() != setsWarning) { - throwWarningException(klass, name, true, "Field.setInt()", setsWarning); - } + clearWarning(); + if (!Reflection.canGetField(klass, name)) { + throwAccessException(klass, name, true, "Field.getInt()"); + } + if (hasPendingWarning() != setsWarning) { + throwWarningException(klass, name, true, "Field.getInt()", setsWarning); + } - clearWarning(); - if (!JNI.canGetField(klass, name, isStatic)) { - throwAccessException(klass, name, true, "getIntField"); - } - if (hasPendingWarning() != setsWarning) { - throwWarningException(klass, name, true, "getIntField", setsWarning); - } + clearWarning(); + if (!Reflection.canSetField(klass, name)) { + throwAccessException(klass, name, true, "Field.setInt()"); + } + if (hasPendingWarning() != setsWarning) { + throwWarningException(klass, name, true, "Field.setInt()", setsWarning); + } - clearWarning(); - if (!JNI.canSetField(klass, name, isStatic)) { - throwAccessException(klass, name, true, "setIntField"); - } - if (hasPendingWarning() != setsWarning) { - throwWarningException(klass, name, true, "setIntField", setsWarning); - } + clearWarning(); + if (!JNI.canGetField(klass, name, isStatic)) { + throwAccessException(klass, name, true, "getIntField"); + } + if (hasPendingWarning() != setsWarning) { + throwWarningException(klass, name, true, "getIntField", setsWarning); } - // Test that callbacks are invoked correctly. clearWarning(); - if (setsWarning || !canDiscover) { - checkMemberCallback(klass, name, isPublic, true /* isField */); + if (!JNI.canSetField(klass, name, isStatic)) { + throwAccessException(klass, name, true, "setIntField"); + } + if (hasPendingWarning() != setsWarning) { + throwWarningException(klass, name, true, "setIntField", setsWarning); } } @@ -299,46 +257,42 @@ public class ChildClass { // Finish here if we could not discover the field. - if (canDiscover) { - // Test that modifiers are unaffected. + if (!canDiscover) { + return; + } - if (Reflection.canObserveMethodHiddenAccessFlags(klass, name)) { - throwModifiersException(klass, name, false); - } + // Test that modifiers are unaffected. - // Test whether we can invoke the method. This skips non-static interface methods. + if (Reflection.canObserveMethodHiddenAccessFlags(klass, name)) { + throwModifiersException(klass, name, false); + } - if (!klass.isInterface() || isStatic) { - clearWarning(); - if (!Reflection.canInvokeMethod(klass, name)) { - throwAccessException(klass, name, false, "invoke()"); - } - if (hasPendingWarning() != setsWarning) { - throwWarningException(klass, name, false, "invoke()", setsWarning); - } + // Test whether we can invoke the method. This skips non-static interface methods. - clearWarning(); - if (!JNI.canInvokeMethodA(klass, name, isStatic)) { - throwAccessException(klass, name, false, "CallMethodA"); - } - if (hasPendingWarning() != setsWarning) { - throwWarningException(klass, name, false, "CallMethodA()", setsWarning); - } + if (!klass.isInterface() || isStatic) { + clearWarning(); + if (!Reflection.canInvokeMethod(klass, name)) { + throwAccessException(klass, name, false, "invoke()"); + } + if (hasPendingWarning() != setsWarning) { + throwWarningException(klass, name, false, "invoke()", setsWarning); + } - clearWarning(); - if (!JNI.canInvokeMethodV(klass, name, isStatic)) { - throwAccessException(klass, name, false, "CallMethodV"); - } - if (hasPendingWarning() != setsWarning) { - throwWarningException(klass, name, false, "CallMethodV()", setsWarning); - } + clearWarning(); + if (!JNI.canInvokeMethodA(klass, name, isStatic)) { + throwAccessException(klass, name, false, "CallMethodA"); + } + if (hasPendingWarning() != setsWarning) { + throwWarningException(klass, name, false, "CallMethodA()", setsWarning); } - } - // Test that callbacks are invoked correctly. - clearWarning(); - if (setsWarning || !canDiscover) { - checkMemberCallback(klass, name, isPublic, false /* isField */); + clearWarning(); + if (!JNI.canInvokeMethodV(klass, name, isStatic)) { + throwAccessException(klass, name, false, "CallMethodV"); + } + if (hasPendingWarning() != setsWarning) { + throwWarningException(klass, name, false, "CallMethodV()", setsWarning); + } } } |