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