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