summaryrefslogtreecommitdiff
path: root/test/674-hiddenapi/hiddenapi.cc
diff options
context:
space:
mode:
Diffstat (limited to 'test/674-hiddenapi/hiddenapi.cc')
-rw-r--r--test/674-hiddenapi/hiddenapi.cc296
1 files changed, 296 insertions, 0 deletions
diff --git a/test/674-hiddenapi/hiddenapi.cc b/test/674-hiddenapi/hiddenapi.cc
new file mode 100644
index 0000000000..baff6f758d
--- /dev/null
+++ b/test/674-hiddenapi/hiddenapi.cc
@@ -0,0 +1,296 @@
+/*
+ * Copyright (C) 2017 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#include "class_linker.h"
+#include "dex/art_dex_file_loader.h"
+#include "jni.h"
+#include "runtime.h"
+#include "scoped_thread_state_change-inl.h"
+#include "thread.h"
+#include "ti-agent/scoped_utf_chars.h"
+
+namespace art {
+namespace Test674HiddenApi {
+
+extern "C" JNIEXPORT void JNICALL Java_Main_init(JNIEnv*, jclass) {
+ Runtime::Current()->SetHiddenApiChecksEnabled(true);
+ Runtime::Current()->SetDedupeHiddenApiWarnings(false);
+}
+
+extern "C" JNIEXPORT void JNICALL Java_Main_appendToBootClassLoader(
+ JNIEnv* env, jclass, jstring jpath) {
+ ScopedUtfChars utf(env, jpath);
+ const char* path = utf.c_str();
+ if (path == nullptr) {
+ return;
+ }
+
+ ArtDexFileLoader dex_loader;
+ std::string error_msg;
+ std::vector<std::unique_ptr<const DexFile>> dex_files;
+ if (!dex_loader.Open(path,
+ path,
+ /* verify */ false,
+ /* verify_checksum */ true,
+ &error_msg,
+ &dex_files)) {
+ LOG(FATAL) << "Could not open " << path << " for boot classpath extension: " << error_msg;
+ UNREACHABLE();
+ }
+
+ ScopedObjectAccess soa(Thread::Current());
+ for (std::unique_ptr<const DexFile>& dex_file : dex_files) {
+ Runtime::Current()->GetClassLinker()->AppendToBootClassPath(
+ Thread::Current(), *dex_file.release());
+ }
+}
+
+static jobject NewInstance(JNIEnv* env, jclass klass) {
+ jmethodID constructor = env->GetMethodID(klass, "<init>", "()V");
+ if (constructor == NULL) {
+ return NULL;
+ }
+ return env->NewObject(klass, constructor);
+}
+
+extern "C" JNIEXPORT jboolean JNICALL Java_JNI_canDiscoverField(
+ JNIEnv* env, jclass, jclass klass, jstring name, jboolean is_static) {
+ ScopedUtfChars utf_name(env, name);
+ jfieldID field = is_static ? env->GetStaticFieldID(klass, utf_name.c_str(), "I")
+ : env->GetFieldID(klass, utf_name.c_str(), "I");
+ if (field == NULL) {
+ env->ExceptionClear();
+ return JNI_FALSE;
+ }
+
+ return JNI_TRUE;
+}
+
+extern "C" JNIEXPORT jboolean JNICALL Java_JNI_canGetField(
+ JNIEnv* env, jclass, jclass klass, jstring name, jboolean is_static) {
+ ScopedUtfChars utf_name(env, name);
+ jfieldID field = is_static ? env->GetStaticFieldID(klass, utf_name.c_str(), "I")
+ : env->GetFieldID(klass, utf_name.c_str(), "I");
+ if (field == NULL) {
+ env->ExceptionClear();
+ return JNI_FALSE;
+ }
+ if (is_static) {
+ env->GetStaticIntField(klass, field);
+ } else {
+ jobject obj = NewInstance(env, klass);
+ if (obj == NULL) {
+ env->ExceptionDescribe();
+ env->ExceptionClear();
+ return JNI_FALSE;
+ }
+ env->GetIntField(obj, field);
+ }
+
+ if (env->ExceptionOccurred()) {
+ env->ExceptionDescribe();
+ env->ExceptionClear();
+ return JNI_FALSE;
+ }
+
+ return JNI_TRUE;
+}
+
+extern "C" JNIEXPORT jboolean JNICALL Java_JNI_canSetField(
+ JNIEnv* env, jclass, jclass klass, jstring name, jboolean is_static) {
+ ScopedUtfChars utf_name(env, name);
+ jfieldID field = is_static ? env->GetStaticFieldID(klass, utf_name.c_str(), "I")
+ : env->GetFieldID(klass, utf_name.c_str(), "I");
+ if (field == NULL) {
+ env->ExceptionClear();
+ return JNI_FALSE;
+ }
+ if (is_static) {
+ env->SetStaticIntField(klass, field, 42);
+ } else {
+ jobject obj = NewInstance(env, klass);
+ if (obj == NULL) {
+ env->ExceptionDescribe();
+ env->ExceptionClear();
+ return JNI_FALSE;
+ }
+ env->SetIntField(obj, field, 42);
+ }
+
+ if (env->ExceptionOccurred()) {
+ env->ExceptionDescribe();
+ env->ExceptionClear();
+ return JNI_FALSE;
+ }
+
+ return JNI_TRUE;
+}
+
+extern "C" JNIEXPORT jboolean JNICALL Java_JNI_canDiscoverMethod(
+ JNIEnv* env, jclass, jclass klass, jstring name, jboolean is_static) {
+ ScopedUtfChars utf_name(env, name);
+ jmethodID method = is_static ? env->GetStaticMethodID(klass, utf_name.c_str(), "()I")
+ : env->GetMethodID(klass, utf_name.c_str(), "()I");
+ if (method == NULL) {
+ env->ExceptionClear();
+ return JNI_FALSE;
+ }
+
+ return JNI_TRUE;
+}
+
+extern "C" JNIEXPORT jboolean JNICALL Java_JNI_canInvokeMethodA(
+ JNIEnv* env, jclass, jclass klass, jstring name, jboolean is_static) {
+ ScopedUtfChars utf_name(env, name);
+ jmethodID method = is_static ? env->GetStaticMethodID(klass, utf_name.c_str(), "()I")
+ : env->GetMethodID(klass, utf_name.c_str(), "()I");
+ if (method == NULL) {
+ env->ExceptionClear();
+ return JNI_FALSE;
+ }
+
+ if (is_static) {
+ env->CallStaticIntMethodA(klass, method, nullptr);
+ } else {
+ jobject obj = NewInstance(env, klass);
+ if (obj == NULL) {
+ env->ExceptionDescribe();
+ env->ExceptionClear();
+ return JNI_FALSE;
+ }
+ env->CallIntMethodA(obj, method, nullptr);
+ }
+
+ if (env->ExceptionOccurred()) {
+ env->ExceptionDescribe();
+ env->ExceptionClear();
+ return JNI_FALSE;
+ }
+
+ return JNI_TRUE;
+}
+
+extern "C" JNIEXPORT jboolean JNICALL Java_JNI_canInvokeMethodV(
+ JNIEnv* env, jclass, jclass klass, jstring name, jboolean is_static) {
+ ScopedUtfChars utf_name(env, name);
+ jmethodID method = is_static ? env->GetStaticMethodID(klass, utf_name.c_str(), "()I")
+ : env->GetMethodID(klass, utf_name.c_str(), "()I");
+ if (method == NULL) {
+ env->ExceptionClear();
+ return JNI_FALSE;
+ }
+
+ if (is_static) {
+ env->CallStaticIntMethod(klass, method);
+ } else {
+ jobject obj = NewInstance(env, klass);
+ if (obj == NULL) {
+ env->ExceptionDescribe();
+ env->ExceptionClear();
+ return JNI_FALSE;
+ }
+ env->CallIntMethod(obj, method);
+ }
+
+ if (env->ExceptionOccurred()) {
+ env->ExceptionDescribe();
+ env->ExceptionClear();
+ return JNI_FALSE;
+ }
+
+ return JNI_TRUE;
+}
+
+static constexpr size_t kConstructorSignatureLength = 5; // e.g. (IZ)V
+static constexpr size_t kNumConstructorArgs = kConstructorSignatureLength - 3;
+
+extern "C" JNIEXPORT jboolean JNICALL Java_JNI_canDiscoverConstructor(
+ JNIEnv* env, jclass, jclass klass, jstring args) {
+ ScopedUtfChars utf_args(env, args);
+ jmethodID constructor = env->GetMethodID(klass, "<init>", utf_args.c_str());
+ if (constructor == NULL) {
+ env->ExceptionClear();
+ return JNI_FALSE;
+ }
+
+ return JNI_TRUE;
+}
+
+extern "C" JNIEXPORT jboolean JNICALL Java_JNI_canInvokeConstructorA(
+ JNIEnv* env, jclass, jclass klass, jstring args) {
+ ScopedUtfChars utf_args(env, args);
+ jmethodID constructor = env->GetMethodID(klass, "<init>", utf_args.c_str());
+ if (constructor == NULL) {
+ env->ExceptionClear();
+ return JNI_FALSE;
+ }
+
+ // CheckJNI won't allow out-of-range values, so just zero everything.
+ CHECK_EQ(strlen(utf_args.c_str()), kConstructorSignatureLength);
+ size_t initargs_size = sizeof(jvalue) * kNumConstructorArgs;
+ jvalue *initargs = reinterpret_cast<jvalue*>(alloca(initargs_size));
+ memset(initargs, 0, initargs_size);
+
+ env->NewObjectA(klass, constructor, initargs);
+ if (env->ExceptionOccurred()) {
+ env->ExceptionDescribe();
+ env->ExceptionClear();
+ return JNI_FALSE;
+ }
+
+ return JNI_TRUE;
+}
+
+extern "C" JNIEXPORT jboolean JNICALL Java_JNI_canInvokeConstructorV(
+ JNIEnv* env, jclass, jclass klass, jstring args) {
+ ScopedUtfChars utf_args(env, args);
+ jmethodID constructor = env->GetMethodID(klass, "<init>", utf_args.c_str());
+ if (constructor == NULL) {
+ env->ExceptionClear();
+ return JNI_FALSE;
+ }
+
+ // CheckJNI won't allow out-of-range values, so just zero everything.
+ CHECK_EQ(strlen(utf_args.c_str()), kConstructorSignatureLength);
+ size_t initargs_size = sizeof(jvalue) * kNumConstructorArgs;
+ jvalue *initargs = reinterpret_cast<jvalue*>(alloca(initargs_size));
+ memset(initargs, 0, initargs_size);
+
+ static_assert(kNumConstructorArgs == 2, "Change the varargs below if you change the constant");
+ env->NewObject(klass, constructor, initargs[0], initargs[1]);
+ if (env->ExceptionOccurred()) {
+ env->ExceptionDescribe();
+ env->ExceptionClear();
+ return JNI_FALSE;
+ }
+
+ return JNI_TRUE;
+}
+
+extern "C" JNIEXPORT jint JNICALL Java_Reflection_getHiddenApiAccessFlags(JNIEnv*, jclass) {
+ return static_cast<jint>(kAccHiddenApiBits);
+}
+
+extern "C" JNIEXPORT jboolean JNICALL Java_ChildClass_hasPendingWarning(JNIEnv*, jclass) {
+ return Runtime::Current()->HasPendingHiddenApiWarning();
+}
+
+extern "C" JNIEXPORT void JNICALL Java_ChildClass_clearWarning(JNIEnv*, jclass) {
+ Runtime::Current()->SetPendingHiddenApiWarning(false);
+}
+
+} // namespace Test674HiddenApi
+} // namespace art