hiddenapi.cc revision 5a61bb7969347ffe8e0bf4f4dff841cc6c21ed85
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#include "class_linker.h" 18#include "dex/art_dex_file_loader.h" 19#include "jni.h" 20#include "runtime.h" 21#include "scoped_thread_state_change-inl.h" 22#include "thread.h" 23#include "ti-agent/scoped_utf_chars.h" 24 25namespace art { 26namespace Test674HiddenApi { 27 28extern "C" JNIEXPORT void JNICALL Java_Main_init(JNIEnv*, jclass) { 29 Runtime::Current()->SetHiddenApiChecksEnabled(true); 30} 31 32extern "C" JNIEXPORT void JNICALL Java_Main_appendToBootClassLoader( 33 JNIEnv* env, jclass, jstring jpath) { 34 ScopedUtfChars utf(env, jpath); 35 const char* path = utf.c_str(); 36 if (path == nullptr) { 37 return; 38 } 39 40 ArtDexFileLoader dex_loader; 41 std::string error_msg; 42 std::vector<std::unique_ptr<const DexFile>> dex_files; 43 if (!dex_loader.Open(path, 44 path, 45 /* verify */ false, 46 /* verify_checksum */ true, 47 &error_msg, 48 &dex_files)) { 49 LOG(FATAL) << "Could not open " << path << " for boot classpath extension: " << error_msg; 50 UNREACHABLE(); 51 } 52 53 ScopedObjectAccess soa(Thread::Current()); 54 for (std::unique_ptr<const DexFile>& dex_file : dex_files) { 55 Runtime::Current()->GetClassLinker()->AppendToBootClassPath( 56 Thread::Current(), *dex_file.release()); 57 } 58} 59 60static jobject NewInstance(JNIEnv* env, jclass klass) { 61 jmethodID constructor = env->GetMethodID(klass, "<init>", "()V"); 62 if (constructor == NULL) { 63 return NULL; 64 } 65 return env->NewObject(klass, constructor); 66} 67 68extern "C" JNIEXPORT jboolean JNICALL Java_JNI_canDiscoverField( 69 JNIEnv* env, jclass, jclass klass, jstring name, jboolean is_static) { 70 ScopedUtfChars utf_name(env, name); 71 jfieldID field = is_static ? env->GetStaticFieldID(klass, utf_name.c_str(), "I") 72 : env->GetFieldID(klass, utf_name.c_str(), "I"); 73 if (field == NULL) { 74 env->ExceptionClear(); 75 return JNI_FALSE; 76 } 77 78 return JNI_TRUE; 79} 80 81extern "C" JNIEXPORT jboolean JNICALL Java_JNI_canGetField( 82 JNIEnv* env, jclass, jclass klass, jstring name, jboolean is_static) { 83 ScopedUtfChars utf_name(env, name); 84 jfieldID field = is_static ? env->GetStaticFieldID(klass, utf_name.c_str(), "I") 85 : env->GetFieldID(klass, utf_name.c_str(), "I"); 86 if (field == NULL) { 87 env->ExceptionClear(); 88 return JNI_FALSE; 89 } 90 if (is_static) { 91 env->GetStaticIntField(klass, field); 92 } else { 93 jobject obj = NewInstance(env, klass); 94 if (obj == NULL) { 95 env->ExceptionDescribe(); 96 env->ExceptionClear(); 97 return JNI_FALSE; 98 } 99 env->GetIntField(obj, field); 100 } 101 102 if (env->ExceptionOccurred()) { 103 env->ExceptionDescribe(); 104 env->ExceptionClear(); 105 return JNI_FALSE; 106 } 107 108 return JNI_TRUE; 109} 110 111extern "C" JNIEXPORT jboolean JNICALL Java_JNI_canSetField( 112 JNIEnv* env, jclass, jclass klass, jstring name, jboolean is_static) { 113 ScopedUtfChars utf_name(env, name); 114 jfieldID field = is_static ? env->GetStaticFieldID(klass, utf_name.c_str(), "I") 115 : env->GetFieldID(klass, utf_name.c_str(), "I"); 116 if (field == NULL) { 117 env->ExceptionClear(); 118 return JNI_FALSE; 119 } 120 if (is_static) { 121 env->SetStaticIntField(klass, field, 42); 122 } else { 123 jobject obj = NewInstance(env, klass); 124 if (obj == NULL) { 125 env->ExceptionDescribe(); 126 env->ExceptionClear(); 127 return JNI_FALSE; 128 } 129 env->SetIntField(obj, field, 42); 130 } 131 132 if (env->ExceptionOccurred()) { 133 env->ExceptionDescribe(); 134 env->ExceptionClear(); 135 return JNI_FALSE; 136 } 137 138 return JNI_TRUE; 139} 140 141extern "C" JNIEXPORT jboolean JNICALL Java_JNI_canDiscoverMethod( 142 JNIEnv* env, jclass, jclass klass, jstring name, jboolean is_static) { 143 ScopedUtfChars utf_name(env, name); 144 jmethodID method = is_static ? env->GetStaticMethodID(klass, utf_name.c_str(), "()I") 145 : env->GetMethodID(klass, utf_name.c_str(), "()I"); 146 if (method == NULL) { 147 env->ExceptionClear(); 148 return JNI_FALSE; 149 } 150 151 return JNI_TRUE; 152} 153 154extern "C" JNIEXPORT jboolean JNICALL Java_JNI_canInvokeMethodA( 155 JNIEnv* env, jclass, jclass klass, jstring name, jboolean is_static) { 156 ScopedUtfChars utf_name(env, name); 157 jmethodID method = is_static ? env->GetStaticMethodID(klass, utf_name.c_str(), "()I") 158 : env->GetMethodID(klass, utf_name.c_str(), "()I"); 159 if (method == NULL) { 160 env->ExceptionClear(); 161 return JNI_FALSE; 162 } 163 164 if (is_static) { 165 env->CallStaticIntMethodA(klass, method, nullptr); 166 } else { 167 jobject obj = NewInstance(env, klass); 168 if (obj == NULL) { 169 env->ExceptionDescribe(); 170 env->ExceptionClear(); 171 return JNI_FALSE; 172 } 173 env->CallIntMethodA(obj, method, nullptr); 174 } 175 176 if (env->ExceptionOccurred()) { 177 env->ExceptionDescribe(); 178 env->ExceptionClear(); 179 return JNI_FALSE; 180 } 181 182 return JNI_TRUE; 183} 184 185extern "C" JNIEXPORT jboolean JNICALL Java_JNI_canInvokeMethodV( 186 JNIEnv* env, jclass, jclass klass, jstring name, jboolean is_static) { 187 ScopedUtfChars utf_name(env, name); 188 jmethodID method = is_static ? env->GetStaticMethodID(klass, utf_name.c_str(), "()I") 189 : env->GetMethodID(klass, utf_name.c_str(), "()I"); 190 if (method == NULL) { 191 env->ExceptionClear(); 192 return JNI_FALSE; 193 } 194 195 if (is_static) { 196 env->CallStaticIntMethod(klass, method); 197 } else { 198 jobject obj = NewInstance(env, klass); 199 if (obj == NULL) { 200 env->ExceptionDescribe(); 201 env->ExceptionClear(); 202 return JNI_FALSE; 203 } 204 env->CallIntMethod(obj, method); 205 } 206 207 if (env->ExceptionOccurred()) { 208 env->ExceptionDescribe(); 209 env->ExceptionClear(); 210 return JNI_FALSE; 211 } 212 213 return JNI_TRUE; 214} 215 216static constexpr size_t kConstructorSignatureLength = 5; // e.g. (IZ)V 217static constexpr size_t kNumConstructorArgs = kConstructorSignatureLength - 3; 218 219extern "C" JNIEXPORT jboolean JNICALL Java_JNI_canDiscoverConstructor( 220 JNIEnv* env, jclass, jclass klass, jstring args) { 221 ScopedUtfChars utf_args(env, args); 222 jmethodID constructor = env->GetMethodID(klass, "<init>", utf_args.c_str()); 223 if (constructor == NULL) { 224 env->ExceptionClear(); 225 return JNI_FALSE; 226 } 227 228 return JNI_TRUE; 229} 230 231extern "C" JNIEXPORT jboolean JNICALL Java_JNI_canInvokeConstructorA( 232 JNIEnv* env, jclass, jclass klass, jstring args) { 233 ScopedUtfChars utf_args(env, args); 234 jmethodID constructor = env->GetMethodID(klass, "<init>", utf_args.c_str()); 235 if (constructor == NULL) { 236 env->ExceptionClear(); 237 return JNI_FALSE; 238 } 239 240 // CheckJNI won't allow out-of-range values, so just zero everything. 241 CHECK_EQ(strlen(utf_args.c_str()), kConstructorSignatureLength); 242 size_t initargs_size = sizeof(jvalue) * kNumConstructorArgs; 243 jvalue *initargs = reinterpret_cast<jvalue*>(alloca(initargs_size)); 244 memset(initargs, 0, initargs_size); 245 246 env->NewObjectA(klass, constructor, initargs); 247 if (env->ExceptionOccurred()) { 248 env->ExceptionDescribe(); 249 env->ExceptionClear(); 250 return JNI_FALSE; 251 } 252 253 return JNI_TRUE; 254} 255 256extern "C" JNIEXPORT jboolean JNICALL Java_JNI_canInvokeConstructorV( 257 JNIEnv* env, jclass, jclass klass, jstring args) { 258 ScopedUtfChars utf_args(env, args); 259 jmethodID constructor = env->GetMethodID(klass, "<init>", utf_args.c_str()); 260 if (constructor == NULL) { 261 env->ExceptionClear(); 262 return JNI_FALSE; 263 } 264 265 // CheckJNI won't allow out-of-range values, so just zero everything. 266 CHECK_EQ(strlen(utf_args.c_str()), kConstructorSignatureLength); 267 size_t initargs_size = sizeof(jvalue) * kNumConstructorArgs; 268 jvalue *initargs = reinterpret_cast<jvalue*>(alloca(initargs_size)); 269 memset(initargs, 0, initargs_size); 270 271 static_assert(kNumConstructorArgs == 2, "Change the varargs below if you change the constant"); 272 env->NewObject(klass, constructor, initargs[0], initargs[1]); 273 if (env->ExceptionOccurred()) { 274 env->ExceptionDescribe(); 275 env->ExceptionClear(); 276 return JNI_FALSE; 277 } 278 279 return JNI_TRUE; 280} 281 282extern "C" JNIEXPORT jint JNICALL Java_Reflection_getHiddenApiAccessFlags(JNIEnv*, jclass) { 283 return static_cast<jint>(kAccHiddenApiBits); 284} 285 286extern "C" JNIEXPORT jboolean JNICALL Java_ChildClass_hasPendingWarning(JNIEnv*, jclass) { 287 return false; 288} 289 290extern "C" JNIEXPORT void JNICALL Java_ChildClass_clearWarning(JNIEnv*, jclass) { 291 return; 292} 293 294} // namespace Test674HiddenApi 295} // namespace art 296