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