Home | History | Annotate | Download | only in native
      1 /*
      2  * Copyright (C) 2006 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 #define LOG_TAG "JNIHelp"
     18 
     19 #include "JNIHelp.h"
     20 
     21 #include <android/log.h>
     22 #include "log_compat.h"
     23 
     24 #include <stdio.h>
     25 #include <stdlib.h>
     26 #include <string.h>
     27 #include <assert.h>
     28 
     29 /**
     30  * Equivalent to ScopedLocalRef, but for C_JNIEnv instead. (And slightly more powerful.)
     31  */
     32 template<typename T>
     33 class scoped_local_ref {
     34 public:
     35     scoped_local_ref(C_JNIEnv* env, T localRef = NULL)
     36     : mEnv(env), mLocalRef(localRef)
     37     {
     38     }
     39 
     40     ~scoped_local_ref() {
     41         reset();
     42     }
     43 
     44     void reset(T localRef = NULL) {
     45         if (mLocalRef != NULL) {
     46             (*mEnv)->DeleteLocalRef(reinterpret_cast<JNIEnv*>(mEnv), mLocalRef);
     47             mLocalRef = localRef;
     48         }
     49     }
     50 
     51     T get() const {
     52         return mLocalRef;
     53     }
     54 
     55 private:
     56     C_JNIEnv* mEnv;
     57     T mLocalRef;
     58 
     59     // Disallow copy and assignment.
     60     scoped_local_ref(const scoped_local_ref&);
     61     void operator=(const scoped_local_ref&);
     62 };
     63 
     64 static jclass findClass(C_JNIEnv* env, const char* className) {
     65     JNIEnv* e = reinterpret_cast<JNIEnv*>(env);
     66     return (*env)->FindClass(e, className);
     67 }
     68 
     69 extern "C" int jniRegisterNativeMethods(C_JNIEnv* env, const char* className,
     70     const JNINativeMethod* gMethods, int numMethods)
     71 {
     72     JNIEnv* e = reinterpret_cast<JNIEnv*>(env);
     73 
     74     ALOGV("Registering %s's %d native methods...", className, numMethods);
     75 
     76     scoped_local_ref<jclass> c(env, findClass(env, className));
     77     if (c.get() == NULL) {
     78         char* msg;
     79         asprintf(&msg, "Native registration unable to find class '%s'; aborting...", className);
     80         e->FatalError(msg);
     81     }
     82 
     83     if ((*env)->RegisterNatives(e, c.get(), gMethods, numMethods) < 0) {
     84         char* msg;
     85         asprintf(&msg, "RegisterNatives failed for '%s'; aborting...", className);
     86         e->FatalError(msg);
     87     }
     88 
     89     return 0;
     90 }
     91 
     92 extern "C" int jniThrowException(C_JNIEnv* c_env, const char* className, const char* msg) {
     93     JNIEnv* env = reinterpret_cast<JNIEnv*>(c_env);
     94     jclass exceptionClass = env->FindClass(className);
     95 
     96     if (exceptionClass == NULL) {
     97         ALOGD("Unable to find exception class %s", className);
     98         /* ClassNotFoundException now pending */
     99         return -1;
    100     }
    101 
    102     if (env->ThrowNew(exceptionClass, msg) != JNI_OK) {
    103         ALOGD("Failed throwing '%s' '%s'", className, msg);
    104         /* an exception, most likely OOM, will now be pending */
    105         return -1;
    106     }
    107 
    108     env->DeleteLocalRef(exceptionClass);
    109     return 0;
    110 }
    111 
    112 int jniThrowExceptionFmt(C_JNIEnv* env, const char* className, const char* fmt, va_list args) {
    113     char msgBuf[512];
    114     vsnprintf(msgBuf, sizeof(msgBuf), fmt, args);
    115     return jniThrowException(env, className, msgBuf);
    116 }
    117 
    118 int jniThrowNullPointerException(C_JNIEnv* env, const char* msg) {
    119     return jniThrowException(env, "java/lang/NullPointerException", msg);
    120 }
    121 
    122 int jniThrowRuntimeException(C_JNIEnv* env, const char* msg) {
    123     return jniThrowException(env, "java/lang/RuntimeException", msg);
    124 }
    125 
    126 int jniThrowIOException(C_JNIEnv* env, int errnum) {
    127     char buffer[80];
    128     const char* message = jniStrError(errnum, buffer, sizeof(buffer));
    129     return jniThrowException(env, "java/io/IOException", message);
    130 }
    131 
    132 const char* jniStrError(int errnum, char* buf, size_t buflen) {
    133 #if __GLIBC__
    134     // Note: glibc has a nonstandard strerror_r that returns char* rather than POSIX's int.
    135     // char *strerror_r(int errnum, char *buf, size_t n);
    136     return strerror_r(errnum, buf, buflen);
    137 #else
    138     int rc = strerror_r(errnum, buf, buflen);
    139     if (rc != 0) {
    140         // (POSIX only guarantees a value other than 0. The safest
    141         // way to implement this function is to use C++ and overload on the
    142         // type of strerror_r to accurately distinguish GNU from POSIX.)
    143         snprintf(buf, buflen, "errno %d", errnum);
    144     }
    145     return buf;
    146 #endif
    147 }
    148 
    149 int jniGetFDFromFileDescriptor(C_JNIEnv* env, jobject fileDescriptor) {
    150     JNIEnv* e = reinterpret_cast<JNIEnv*>(env);
    151     scoped_local_ref<jclass> localClass(env, e->FindClass("java/io/FileDescriptor"));
    152     static jfieldID fid = e->GetFieldID(localClass.get(), "descriptor", "I");
    153     if (fileDescriptor != NULL) {
    154         return (*env)->GetIntField(e, fileDescriptor, fid);
    155     } else {
    156         return -1;
    157     }
    158 }
    159