13e46e4ee56c8e37158f46941dedd5b436d724baaKenny Root/* 23e46e4ee56c8e37158f46941dedd5b436d724baaKenny Root * Copyright (C) 2006 The Android Open Source Project 33e46e4ee56c8e37158f46941dedd5b436d724baaKenny Root * 43e46e4ee56c8e37158f46941dedd5b436d724baaKenny Root * Licensed under the Apache License, Version 2.0 (the "License"); 53e46e4ee56c8e37158f46941dedd5b436d724baaKenny Root * you may not use this file except in compliance with the License. 63e46e4ee56c8e37158f46941dedd5b436d724baaKenny Root * You may obtain a copy of the License at 73e46e4ee56c8e37158f46941dedd5b436d724baaKenny Root * 83e46e4ee56c8e37158f46941dedd5b436d724baaKenny Root * http://www.apache.org/licenses/LICENSE-2.0 93e46e4ee56c8e37158f46941dedd5b436d724baaKenny Root * 103e46e4ee56c8e37158f46941dedd5b436d724baaKenny Root * Unless required by applicable law or agreed to in writing, software 113e46e4ee56c8e37158f46941dedd5b436d724baaKenny Root * distributed under the License is distributed on an "AS IS" BASIS, 123e46e4ee56c8e37158f46941dedd5b436d724baaKenny Root * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 133e46e4ee56c8e37158f46941dedd5b436d724baaKenny Root * See the License for the specific language governing permissions and 143e46e4ee56c8e37158f46941dedd5b436d724baaKenny Root * limitations under the License. 153e46e4ee56c8e37158f46941dedd5b436d724baaKenny Root */ 163e46e4ee56c8e37158f46941dedd5b436d724baaKenny Root 173e46e4ee56c8e37158f46941dedd5b436d724baaKenny Root#define LOG_TAG "JNIHelp" 183e46e4ee56c8e37158f46941dedd5b436d724baaKenny Root 193e46e4ee56c8e37158f46941dedd5b436d724baaKenny Root#include "JNIHelp.h" 203e46e4ee56c8e37158f46941dedd5b436d724baaKenny Root 213e46e4ee56c8e37158f46941dedd5b436d724baaKenny Root#include <android/log.h> 223e46e4ee56c8e37158f46941dedd5b436d724baaKenny Root#include "log_compat.h" 233e46e4ee56c8e37158f46941dedd5b436d724baaKenny Root 243e46e4ee56c8e37158f46941dedd5b436d724baaKenny Root#include <stdio.h> 253e46e4ee56c8e37158f46941dedd5b436d724baaKenny Root#include <stdlib.h> 263e46e4ee56c8e37158f46941dedd5b436d724baaKenny Root#include <string.h> 273e46e4ee56c8e37158f46941dedd5b436d724baaKenny Root#include <assert.h> 283e46e4ee56c8e37158f46941dedd5b436d724baaKenny Root 293e46e4ee56c8e37158f46941dedd5b436d724baaKenny Root/** 303e46e4ee56c8e37158f46941dedd5b436d724baaKenny Root * Equivalent to ScopedLocalRef, but for C_JNIEnv instead. (And slightly more powerful.) 313e46e4ee56c8e37158f46941dedd5b436d724baaKenny Root */ 323e46e4ee56c8e37158f46941dedd5b436d724baaKenny Roottemplate<typename T> 333e46e4ee56c8e37158f46941dedd5b436d724baaKenny Rootclass scoped_local_ref { 343e46e4ee56c8e37158f46941dedd5b436d724baaKenny Rootpublic: 353e46e4ee56c8e37158f46941dedd5b436d724baaKenny Root scoped_local_ref(C_JNIEnv* env, T localRef = NULL) 363e46e4ee56c8e37158f46941dedd5b436d724baaKenny Root : mEnv(env), mLocalRef(localRef) 373e46e4ee56c8e37158f46941dedd5b436d724baaKenny Root { 383e46e4ee56c8e37158f46941dedd5b436d724baaKenny Root } 393e46e4ee56c8e37158f46941dedd5b436d724baaKenny Root 403e46e4ee56c8e37158f46941dedd5b436d724baaKenny Root ~scoped_local_ref() { 413e46e4ee56c8e37158f46941dedd5b436d724baaKenny Root reset(); 423e46e4ee56c8e37158f46941dedd5b436d724baaKenny Root } 433e46e4ee56c8e37158f46941dedd5b436d724baaKenny Root 443e46e4ee56c8e37158f46941dedd5b436d724baaKenny Root void reset(T localRef = NULL) { 453e46e4ee56c8e37158f46941dedd5b436d724baaKenny Root if (mLocalRef != NULL) { 463e46e4ee56c8e37158f46941dedd5b436d724baaKenny Root (*mEnv)->DeleteLocalRef(reinterpret_cast<JNIEnv*>(mEnv), mLocalRef); 473e46e4ee56c8e37158f46941dedd5b436d724baaKenny Root mLocalRef = localRef; 483e46e4ee56c8e37158f46941dedd5b436d724baaKenny Root } 493e46e4ee56c8e37158f46941dedd5b436d724baaKenny Root } 503e46e4ee56c8e37158f46941dedd5b436d724baaKenny Root 513e46e4ee56c8e37158f46941dedd5b436d724baaKenny Root T get() const { 523e46e4ee56c8e37158f46941dedd5b436d724baaKenny Root return mLocalRef; 533e46e4ee56c8e37158f46941dedd5b436d724baaKenny Root } 543e46e4ee56c8e37158f46941dedd5b436d724baaKenny Root 553e46e4ee56c8e37158f46941dedd5b436d724baaKenny Rootprivate: 563e46e4ee56c8e37158f46941dedd5b436d724baaKenny Root C_JNIEnv* mEnv; 573e46e4ee56c8e37158f46941dedd5b436d724baaKenny Root T mLocalRef; 583e46e4ee56c8e37158f46941dedd5b436d724baaKenny Root 593e46e4ee56c8e37158f46941dedd5b436d724baaKenny Root // Disallow copy and assignment. 603e46e4ee56c8e37158f46941dedd5b436d724baaKenny Root scoped_local_ref(const scoped_local_ref&); 613e46e4ee56c8e37158f46941dedd5b436d724baaKenny Root void operator=(const scoped_local_ref&); 623e46e4ee56c8e37158f46941dedd5b436d724baaKenny Root}; 633e46e4ee56c8e37158f46941dedd5b436d724baaKenny Root 643e46e4ee56c8e37158f46941dedd5b436d724baaKenny Rootstatic jclass findClass(C_JNIEnv* env, const char* className) { 653e46e4ee56c8e37158f46941dedd5b436d724baaKenny Root JNIEnv* e = reinterpret_cast<JNIEnv*>(env); 663e46e4ee56c8e37158f46941dedd5b436d724baaKenny Root return (*env)->FindClass(e, className); 673e46e4ee56c8e37158f46941dedd5b436d724baaKenny Root} 683e46e4ee56c8e37158f46941dedd5b436d724baaKenny Root 693e46e4ee56c8e37158f46941dedd5b436d724baaKenny Rootextern "C" int jniRegisterNativeMethods(C_JNIEnv* env, const char* className, 703e46e4ee56c8e37158f46941dedd5b436d724baaKenny Root const JNINativeMethod* gMethods, int numMethods) 713e46e4ee56c8e37158f46941dedd5b436d724baaKenny Root{ 723e46e4ee56c8e37158f46941dedd5b436d724baaKenny Root JNIEnv* e = reinterpret_cast<JNIEnv*>(env); 733e46e4ee56c8e37158f46941dedd5b436d724baaKenny Root 743e46e4ee56c8e37158f46941dedd5b436d724baaKenny Root ALOGV("Registering %s's %d native methods...", className, numMethods); 753e46e4ee56c8e37158f46941dedd5b436d724baaKenny Root 763e46e4ee56c8e37158f46941dedd5b436d724baaKenny Root scoped_local_ref<jclass> c(env, findClass(env, className)); 773e46e4ee56c8e37158f46941dedd5b436d724baaKenny Root if (c.get() == NULL) { 783e46e4ee56c8e37158f46941dedd5b436d724baaKenny Root char* msg; 793e46e4ee56c8e37158f46941dedd5b436d724baaKenny Root asprintf(&msg, "Native registration unable to find class '%s'; aborting...", className); 803e46e4ee56c8e37158f46941dedd5b436d724baaKenny Root e->FatalError(msg); 813e46e4ee56c8e37158f46941dedd5b436d724baaKenny Root } 823e46e4ee56c8e37158f46941dedd5b436d724baaKenny Root 833e46e4ee56c8e37158f46941dedd5b436d724baaKenny Root if ((*env)->RegisterNatives(e, c.get(), gMethods, numMethods) < 0) { 843e46e4ee56c8e37158f46941dedd5b436d724baaKenny Root char* msg; 853e46e4ee56c8e37158f46941dedd5b436d724baaKenny Root asprintf(&msg, "RegisterNatives failed for '%s'; aborting...", className); 863e46e4ee56c8e37158f46941dedd5b436d724baaKenny Root e->FatalError(msg); 873e46e4ee56c8e37158f46941dedd5b436d724baaKenny Root } 883e46e4ee56c8e37158f46941dedd5b436d724baaKenny Root 893e46e4ee56c8e37158f46941dedd5b436d724baaKenny Root return 0; 903e46e4ee56c8e37158f46941dedd5b436d724baaKenny Root} 913e46e4ee56c8e37158f46941dedd5b436d724baaKenny Root 923e46e4ee56c8e37158f46941dedd5b436d724baaKenny Rootextern "C" int jniThrowException(C_JNIEnv* c_env, const char* className, const char* msg) { 933e46e4ee56c8e37158f46941dedd5b436d724baaKenny Root JNIEnv* env = reinterpret_cast<JNIEnv*>(c_env); 943e46e4ee56c8e37158f46941dedd5b436d724baaKenny Root jclass exceptionClass = env->FindClass(className); 953e46e4ee56c8e37158f46941dedd5b436d724baaKenny Root 963e46e4ee56c8e37158f46941dedd5b436d724baaKenny Root if (exceptionClass == NULL) { 973e46e4ee56c8e37158f46941dedd5b436d724baaKenny Root ALOGD("Unable to find exception class %s", className); 983e46e4ee56c8e37158f46941dedd5b436d724baaKenny Root /* ClassNotFoundException now pending */ 993e46e4ee56c8e37158f46941dedd5b436d724baaKenny Root return -1; 1003e46e4ee56c8e37158f46941dedd5b436d724baaKenny Root } 1013e46e4ee56c8e37158f46941dedd5b436d724baaKenny Root 1023e46e4ee56c8e37158f46941dedd5b436d724baaKenny Root if (env->ThrowNew(exceptionClass, msg) != JNI_OK) { 1033e46e4ee56c8e37158f46941dedd5b436d724baaKenny Root ALOGD("Failed throwing '%s' '%s'", className, msg); 1043e46e4ee56c8e37158f46941dedd5b436d724baaKenny Root /* an exception, most likely OOM, will now be pending */ 1053e46e4ee56c8e37158f46941dedd5b436d724baaKenny Root return -1; 1063e46e4ee56c8e37158f46941dedd5b436d724baaKenny Root } 1073e46e4ee56c8e37158f46941dedd5b436d724baaKenny Root 1083e46e4ee56c8e37158f46941dedd5b436d724baaKenny Root env->DeleteLocalRef(exceptionClass); 1093e46e4ee56c8e37158f46941dedd5b436d724baaKenny Root return 0; 1103e46e4ee56c8e37158f46941dedd5b436d724baaKenny Root} 1113e46e4ee56c8e37158f46941dedd5b436d724baaKenny Root 1123e46e4ee56c8e37158f46941dedd5b436d724baaKenny Rootint jniThrowExceptionFmt(C_JNIEnv* env, const char* className, const char* fmt, va_list args) { 1133e46e4ee56c8e37158f46941dedd5b436d724baaKenny Root char msgBuf[512]; 1143e46e4ee56c8e37158f46941dedd5b436d724baaKenny Root vsnprintf(msgBuf, sizeof(msgBuf), fmt, args); 1153e46e4ee56c8e37158f46941dedd5b436d724baaKenny Root return jniThrowException(env, className, msgBuf); 1163e46e4ee56c8e37158f46941dedd5b436d724baaKenny Root} 1173e46e4ee56c8e37158f46941dedd5b436d724baaKenny Root 1183e46e4ee56c8e37158f46941dedd5b436d724baaKenny Rootint jniThrowNullPointerException(C_JNIEnv* env, const char* msg) { 1193e46e4ee56c8e37158f46941dedd5b436d724baaKenny Root return jniThrowException(env, "java/lang/NullPointerException", msg); 1203e46e4ee56c8e37158f46941dedd5b436d724baaKenny Root} 1213e46e4ee56c8e37158f46941dedd5b436d724baaKenny Root 1223e46e4ee56c8e37158f46941dedd5b436d724baaKenny Rootint jniThrowRuntimeException(C_JNIEnv* env, const char* msg) { 1233e46e4ee56c8e37158f46941dedd5b436d724baaKenny Root return jniThrowException(env, "java/lang/RuntimeException", msg); 1243e46e4ee56c8e37158f46941dedd5b436d724baaKenny Root} 1253e46e4ee56c8e37158f46941dedd5b436d724baaKenny Root 1263e46e4ee56c8e37158f46941dedd5b436d724baaKenny Rootint jniThrowIOException(C_JNIEnv* env, int errnum) { 1273e46e4ee56c8e37158f46941dedd5b436d724baaKenny Root char buffer[80]; 1283e46e4ee56c8e37158f46941dedd5b436d724baaKenny Root const char* message = jniStrError(errnum, buffer, sizeof(buffer)); 1293e46e4ee56c8e37158f46941dedd5b436d724baaKenny Root return jniThrowException(env, "java/io/IOException", message); 1303e46e4ee56c8e37158f46941dedd5b436d724baaKenny Root} 1313e46e4ee56c8e37158f46941dedd5b436d724baaKenny Root 1323e46e4ee56c8e37158f46941dedd5b436d724baaKenny Rootconst char* jniStrError(int errnum, char* buf, size_t buflen) { 1333e46e4ee56c8e37158f46941dedd5b436d724baaKenny Root#if __GLIBC__ 1343e46e4ee56c8e37158f46941dedd5b436d724baaKenny Root // Note: glibc has a nonstandard strerror_r that returns char* rather than POSIX's int. 1353e46e4ee56c8e37158f46941dedd5b436d724baaKenny Root // char *strerror_r(int errnum, char *buf, size_t n); 1363e46e4ee56c8e37158f46941dedd5b436d724baaKenny Root return strerror_r(errnum, buf, buflen); 1373e46e4ee56c8e37158f46941dedd5b436d724baaKenny Root#else 1383e46e4ee56c8e37158f46941dedd5b436d724baaKenny Root int rc = strerror_r(errnum, buf, buflen); 1393e46e4ee56c8e37158f46941dedd5b436d724baaKenny Root if (rc != 0) { 1403e46e4ee56c8e37158f46941dedd5b436d724baaKenny Root // (POSIX only guarantees a value other than 0. The safest 1413e46e4ee56c8e37158f46941dedd5b436d724baaKenny Root // way to implement this function is to use C++ and overload on the 1423e46e4ee56c8e37158f46941dedd5b436d724baaKenny Root // type of strerror_r to accurately distinguish GNU from POSIX.) 1433e46e4ee56c8e37158f46941dedd5b436d724baaKenny Root snprintf(buf, buflen, "errno %d", errnum); 1443e46e4ee56c8e37158f46941dedd5b436d724baaKenny Root } 1453e46e4ee56c8e37158f46941dedd5b436d724baaKenny Root return buf; 1463e46e4ee56c8e37158f46941dedd5b436d724baaKenny Root#endif 1473e46e4ee56c8e37158f46941dedd5b436d724baaKenny Root} 1483e46e4ee56c8e37158f46941dedd5b436d724baaKenny Root 1493e46e4ee56c8e37158f46941dedd5b436d724baaKenny Rootint jniGetFDFromFileDescriptor(C_JNIEnv* env, jobject fileDescriptor) { 1503e46e4ee56c8e37158f46941dedd5b436d724baaKenny Root JNIEnv* e = reinterpret_cast<JNIEnv*>(env); 1513e46e4ee56c8e37158f46941dedd5b436d724baaKenny Root scoped_local_ref<jclass> localClass(env, e->FindClass("java/io/FileDescriptor")); 1523e46e4ee56c8e37158f46941dedd5b436d724baaKenny Root static jfieldID fid = e->GetFieldID(localClass.get(), "descriptor", "I"); 1533e46e4ee56c8e37158f46941dedd5b436d724baaKenny Root if (fileDescriptor != NULL) { 1543e46e4ee56c8e37158f46941dedd5b436d724baaKenny Root return (*env)->GetIntField(e, fileDescriptor, fid); 1553e46e4ee56c8e37158f46941dedd5b436d724baaKenny Root } else { 1563e46e4ee56c8e37158f46941dedd5b436d724baaKenny Root return -1; 1573e46e4ee56c8e37158f46941dedd5b436d724baaKenny Root } 1583e46e4ee56c8e37158f46941dedd5b436d724baaKenny Root} 159