ALog-priv.h0100644 0000000 0000000 00000003072 13277516016 011570 0ustar000000000 0000000 /* * Copyright 2013 The Android Open Source Project * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ #ifndef NATIVEHELPER_ALOGPRIV_H_ #define NATIVEHELPER_ALOGPRIV_H_ #include #ifndef LOG_NDEBUG #ifdef NDEBUG #define LOG_NDEBUG 1 #else #define LOG_NDEBUG 0 #endif #endif /* * Basic log message macros intended to emulate the behavior of log/log.h * in system core. This should be dependent only on ndk exposed logging * functionality. */ #ifndef ALOG #define ALOG(priority, tag, fmt...) \ __android_log_print(ANDROID_##priority, tag, fmt) #endif #ifndef ALOGV #if LOG_NDEBUG #define ALOGV(...) ((void)0) #else #define ALOGV(...) ((void)ALOG(LOG_VERBOSE, LOG_TAG, __VA_ARGS__)) #endif #endif #ifndef ALOGD #define ALOGD(...) ((void)ALOG(LOG_DEBUG, LOG_TAG, __VA_ARGS__)) #endif #ifndef ALOGI #define ALOGI(...) ((void)ALOG(LOG_INFO, LOG_TAG, __VA_ARGS__)) #endif #ifndef ALOGW #define ALOGW(...) ((void)ALOG(LOG_WARN, LOG_TAG, __VA_ARGS__)) #endif #ifndef ALOGE #define ALOGE(...) ((void)ALOG(LOG_ERROR, LOG_TAG, __VA_ARGS__)) #endif #endif Android.bp0100644 0000000 0000000 00000004264 13277516016 011526 0ustar000000000 0000000 // Copyright (C) 2009 The Android Open Source Project // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at // // http://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an "AS IS" BASIS, // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // See the License for the specific language governing permissions and // limitations under the License. cc_library_headers { name: "jni_headers", host_supported: true, export_include_dirs: ["include_jni"], vendor_available: true, } cc_library { name: "libnativehelper", host_supported: true, srcs: [ "JNIHelp.cpp", "JniConstants.cpp", "toStringArray.cpp", "JniInvocation.cpp", ], target: { android: { srcs: ["AsynchronousCloseMonitor.cpp"], shared_libs: ["libdl"], }, linux: { srcs: ["AsynchronousCloseMonitor.cpp"], host_ldlibs: ["-ldl"], }, }, header_libs: ["jni_headers"], export_header_lib_headers: ["jni_headers"], shared_libs: [ "liblog", ], clang: true, cflags: [ "-Werror", "-fvisibility=protected", ], export_include_dirs: ["include", "platform_include"], } // // NDK-only build for the target (device), using libc++. // - Relies only on NDK exposed functionality. // - This doesn't include JniInvocation. // cc_library_shared { name: "libnativehelper_compat_libc++", clang: true, local_include_dirs: ["include/nativehelper"], export_include_dirs: ["include/nativehelper"], cflags: ["-Werror"], srcs: [ "JNIHelp.cpp", "JniConstants.cpp", "toStringArray.cpp", ], shared_libs: [ "liblog", "libdl", ], sdk_version: "19", stl: "c++_static", } ndk_headers { name: "ndk_jni.h", from: "include_jni", to: "", srcs: ["include_jni/jni.h"], license: "NOTICE", } // // Tests. // subdirs = ["tests"] AsynchronousCloseMonitor.cpp0100644 0000000 0000000 00000007066 13277516016 015363 0ustar000000000 0000000 /* * Copyright (C) 2010 The Android Open Source Project * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ #define LOG_TAG "AsynchronousCloseMonitor" #include "AsynchronousCloseMonitor.h" #include "cutils/log.h" #include #include #include #include /** * We use an intrusive doubly-linked list to keep track of blocked threads. * This gives us O(1) insertion and removal, and means we don't need to do any allocation. * (The objects themselves are stack-allocated.) * Waking potentially-blocked threads when a file descriptor is closed is O(n) in the total number * of blocked threads (not the number of threads actually blocked on the file descriptor in * question). For now at least, this seems like a good compromise for Android. */ static std::mutex blockedThreadListMutex; static AsynchronousCloseMonitor* blockedThreadList = NULL; /** * The specific signal chosen here is arbitrary, but bionic needs to know so that SIGRTMIN * starts at a higher value. */ static const int BLOCKED_THREAD_SIGNAL = __SIGRTMIN + 2; static void blockedThreadSignalHandler(int /*signal*/) { // Do nothing. We only sent this signal for its side-effect of interrupting syscalls. } void AsynchronousCloseMonitor::init() { // Ensure that the signal we send interrupts system calls but doesn't kill threads. // Using sigaction(2) lets us ensure that the SA_RESTART flag is not set. // (The whole reason we're sending this signal is to unblock system calls!) struct sigaction sa; memset(&sa, 0, sizeof(sa)); sa.sa_handler = blockedThreadSignalHandler; sa.sa_flags = 0; int rc = sigaction(BLOCKED_THREAD_SIGNAL, &sa, NULL); if (rc == -1) { ALOGE("setting blocked thread signal handler failed: %s", strerror(errno)); } } void AsynchronousCloseMonitor::signalBlockedThreads(int fd) { std::lock_guard lock(blockedThreadListMutex); for (AsynchronousCloseMonitor* it = blockedThreadList; it != NULL; it = it->mNext) { if (it->mFd == fd) { it->mSignaled = true; pthread_kill(it->mThread, BLOCKED_THREAD_SIGNAL); // Keep going, because there may be more than one thread... } } } bool AsynchronousCloseMonitor::wasSignaled() const { return mSignaled; } AsynchronousCloseMonitor::AsynchronousCloseMonitor(int fd) { std::lock_guard lock(blockedThreadListMutex); // Who are we, and what are we waiting for? mThread = pthread_self(); mFd = fd; mSignaled = false; // Insert ourselves at the head of the intrusive doubly-linked list... mPrev = NULL; mNext = blockedThreadList; if (mNext != NULL) { mNext->mPrev = this; } blockedThreadList = this; } AsynchronousCloseMonitor::~AsynchronousCloseMonitor() { std::lock_guard lock(blockedThreadListMutex); // Unlink ourselves from the intrusive doubly-linked list... if (mNext != NULL) { mNext->mPrev = mPrev; } if (mPrev == NULL) { blockedThreadList = mNext; } else { mPrev->mNext = mNext; } } JNIHelp.cpp0100644 0000000 0000000 00000030347 13277516016 011561 0ustar000000000 0000000 /* * Copyright (C) 2006 The Android Open Source Project * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ #if defined(__ANDROID__) /* libnativehelper is built by NDK 19 in one variant, which doesn't yet have the GNU strerror_r. */ #undef _GNU_SOURCE /* ...but this code uses asprintf, which is a BSD/GNU extension. */ #define _BSD_SOURCE #endif #define LOG_TAG "JNIHelp" #include "JniConstants.h" #include "JNIHelp.h" #include "ALog-priv.h" #include #include #include #include #include /** * Equivalent to ScopedLocalRef, but for C_JNIEnv instead. (And slightly more powerful.) */ template class scoped_local_ref { public: explicit scoped_local_ref(C_JNIEnv* env, T localRef = NULL) : mEnv(env), mLocalRef(localRef) { } ~scoped_local_ref() { reset(); } void reset(T localRef = NULL) { if (mLocalRef != NULL) { (*mEnv)->DeleteLocalRef(reinterpret_cast(mEnv), mLocalRef); mLocalRef = localRef; } } T get() const { return mLocalRef; } private: C_JNIEnv* const mEnv; T mLocalRef; DISALLOW_COPY_AND_ASSIGN(scoped_local_ref); }; static jclass findClass(C_JNIEnv* env, const char* className) { JNIEnv* e = reinterpret_cast(env); return (*env)->FindClass(e, className); } extern "C" int jniRegisterNativeMethods(C_JNIEnv* env, const char* className, const JNINativeMethod* gMethods, int numMethods) { JNIEnv* e = reinterpret_cast(env); ALOGV("Registering %s's %d native methods...", className, numMethods); scoped_local_ref c(env, findClass(env, className)); if (c.get() == NULL) { char* tmp; const char* msg; if (asprintf(&tmp, "Native registration unable to find class '%s'; aborting...", className) == -1) { // Allocation failed, print default warning. msg = "Native registration unable to find class; aborting..."; } else { msg = tmp; } e->FatalError(msg); } if ((*env)->RegisterNatives(e, c.get(), gMethods, numMethods) < 0) { char* tmp; const char* msg; if (asprintf(&tmp, "RegisterNatives failed for '%s'; aborting...", className) == -1) { // Allocation failed, print default warning. msg = "RegisterNatives failed; aborting..."; } else { msg = tmp; } e->FatalError(msg); } return 0; } /* * Returns a human-readable summary of an exception object. The buffer will * be populated with the "binary" class name and, if present, the * exception message. */ static bool getExceptionSummary(C_JNIEnv* env, jthrowable exception, std::string& result) { JNIEnv* e = reinterpret_cast(env); /* get the name of the exception's class */ scoped_local_ref exceptionClass(env, (*env)->GetObjectClass(e, exception)); // can't fail scoped_local_ref classClass(env, (*env)->GetObjectClass(e, exceptionClass.get())); // java.lang.Class, can't fail jmethodID classGetNameMethod = (*env)->GetMethodID(e, classClass.get(), "getName", "()Ljava/lang/String;"); scoped_local_ref classNameStr(env, (jstring) (*env)->CallObjectMethod(e, exceptionClass.get(), classGetNameMethod)); if (classNameStr.get() == NULL) { (*env)->ExceptionClear(e); result = ""; return false; } const char* classNameChars = (*env)->GetStringUTFChars(e, classNameStr.get(), NULL); if (classNameChars == NULL) { (*env)->ExceptionClear(e); result = ""; return false; } result += classNameChars; (*env)->ReleaseStringUTFChars(e, classNameStr.get(), classNameChars); /* if the exception has a detail message, get that */ jmethodID getMessage = (*env)->GetMethodID(e, exceptionClass.get(), "getMessage", "()Ljava/lang/String;"); scoped_local_ref messageStr(env, (jstring) (*env)->CallObjectMethod(e, exception, getMessage)); if (messageStr.get() == NULL) { return true; } result += ": "; const char* messageChars = (*env)->GetStringUTFChars(e, messageStr.get(), NULL); if (messageChars != NULL) { result += messageChars; (*env)->ReleaseStringUTFChars(e, messageStr.get(), messageChars); } else { result += ""; (*env)->ExceptionClear(e); // clear OOM } return true; } /* * Returns an exception (with stack trace) as a string. */ static bool getStackTrace(C_JNIEnv* env, jthrowable exception, std::string& result) { JNIEnv* e = reinterpret_cast(env); scoped_local_ref stringWriterClass(env, findClass(env, "java/io/StringWriter")); if (stringWriterClass.get() == NULL) { return false; } jmethodID stringWriterCtor = (*env)->GetMethodID(e, stringWriterClass.get(), "", "()V"); jmethodID stringWriterToStringMethod = (*env)->GetMethodID(e, stringWriterClass.get(), "toString", "()Ljava/lang/String;"); scoped_local_ref printWriterClass(env, findClass(env, "java/io/PrintWriter")); if (printWriterClass.get() == NULL) { return false; } jmethodID printWriterCtor = (*env)->GetMethodID(e, printWriterClass.get(), "", "(Ljava/io/Writer;)V"); scoped_local_ref stringWriter(env, (*env)->NewObject(e, stringWriterClass.get(), stringWriterCtor)); if (stringWriter.get() == NULL) { return false; } scoped_local_ref printWriter(env, (*env)->NewObject(e, printWriterClass.get(), printWriterCtor, stringWriter.get())); if (printWriter.get() == NULL) { return false; } scoped_local_ref exceptionClass(env, (*env)->GetObjectClass(e, exception)); // can't fail jmethodID printStackTraceMethod = (*env)->GetMethodID(e, exceptionClass.get(), "printStackTrace", "(Ljava/io/PrintWriter;)V"); (*env)->CallVoidMethod(e, exception, printStackTraceMethod, printWriter.get()); if ((*env)->ExceptionCheck(e)) { return false; } scoped_local_ref messageStr(env, (jstring) (*env)->CallObjectMethod(e, stringWriter.get(), stringWriterToStringMethod)); if (messageStr.get() == NULL) { return false; } const char* utfChars = (*env)->GetStringUTFChars(e, messageStr.get(), NULL); if (utfChars == NULL) { return false; } result = utfChars; (*env)->ReleaseStringUTFChars(e, messageStr.get(), utfChars); return true; } extern "C" int jniThrowException(C_JNIEnv* env, const char* className, const char* msg) { JNIEnv* e = reinterpret_cast(env); if ((*env)->ExceptionCheck(e)) { /* TODO: consider creating the new exception with this as "cause" */ scoped_local_ref exception(env, (*env)->ExceptionOccurred(e)); (*env)->ExceptionClear(e); if (exception.get() != NULL) { std::string text; getExceptionSummary(env, exception.get(), text); ALOGW("Discarding pending exception (%s) to throw %s", text.c_str(), className); } } scoped_local_ref exceptionClass(env, findClass(env, className)); if (exceptionClass.get() == NULL) { ALOGE("Unable to find exception class %s", className); /* ClassNotFoundException now pending */ return -1; } if ((*env)->ThrowNew(e, exceptionClass.get(), msg) != JNI_OK) { ALOGE("Failed throwing '%s' '%s'", className, msg); /* an exception, most likely OOM, will now be pending */ return -1; } return 0; } int jniThrowExceptionFmt(C_JNIEnv* env, const char* className, const char* fmt, va_list args) { char msgBuf[512]; vsnprintf(msgBuf, sizeof(msgBuf), fmt, args); return jniThrowException(env, className, msgBuf); } int jniThrowNullPointerException(C_JNIEnv* env, const char* msg) { return jniThrowException(env, "java/lang/NullPointerException", msg); } int jniThrowRuntimeException(C_JNIEnv* env, const char* msg) { return jniThrowException(env, "java/lang/RuntimeException", msg); } int jniThrowIOException(C_JNIEnv* env, int errnum) { char buffer[80]; const char* message = jniStrError(errnum, buffer, sizeof(buffer)); return jniThrowException(env, "java/io/IOException", message); } static std::string jniGetStackTrace(C_JNIEnv* env, jthrowable exception) { JNIEnv* e = reinterpret_cast(env); scoped_local_ref currentException(env, (*env)->ExceptionOccurred(e)); if (exception == NULL) { exception = currentException.get(); if (exception == NULL) { return ""; } } if (currentException.get() != NULL) { (*env)->ExceptionClear(e); } std::string trace; if (!getStackTrace(env, exception, trace)) { (*env)->ExceptionClear(e); getExceptionSummary(env, exception, trace); } if (currentException.get() != NULL) { (*env)->Throw(e, currentException.get()); // rethrow } return trace; } void jniLogException(C_JNIEnv* env, int priority, const char* tag, jthrowable exception) { std::string trace(jniGetStackTrace(env, exception)); __android_log_write(priority, tag, trace.c_str()); } const char* jniStrError(int errnum, char* buf, size_t buflen) { #if __GLIBC__ // Note: glibc has a nonstandard strerror_r that returns char* rather than POSIX's int. // char *strerror_r(int errnum, char *buf, size_t n); return strerror_r(errnum, buf, buflen); #else int rc = strerror_r(errnum, buf, buflen); if (rc != 0) { // (POSIX only guarantees a value other than 0. The safest // way to implement this function is to use C++ and overload on the // type of strerror_r to accurately distinguish GNU from POSIX.) snprintf(buf, buflen, "errno %d", errnum); } return buf; #endif } jobject jniCreateFileDescriptor(C_JNIEnv* env, int fd) { JNIEnv* e = reinterpret_cast(env); JniConstants::init(e); static jmethodID ctor = e->GetMethodID(JniConstants::fileDescriptorClass, "", "()V"); jobject fileDescriptor = (*env)->NewObject(e, JniConstants::fileDescriptorClass, ctor); // NOTE: NewObject ensures that an OutOfMemoryError will be seen by the Java // caller if the alloc fails, so we just return NULL when that happens. if (fileDescriptor != NULL) { jniSetFileDescriptorOfFD(env, fileDescriptor, fd); } return fileDescriptor; } int jniGetFDFromFileDescriptor(C_JNIEnv* env, jobject fileDescriptor) { JNIEnv* e = reinterpret_cast(env); JniConstants::init(e); static jfieldID fid = e->GetFieldID(JniConstants::fileDescriptorClass, "descriptor", "I"); if (fileDescriptor != NULL) { return (*env)->GetIntField(e, fileDescriptor, fid); } else { return -1; } } void jniSetFileDescriptorOfFD(C_JNIEnv* env, jobject fileDescriptor, int value) { JNIEnv* e = reinterpret_cast(env); JniConstants::init(e); static jfieldID fid = e->GetFieldID(JniConstants::fileDescriptorClass, "descriptor", "I"); (*env)->SetIntField(e, fileDescriptor, fid, value); } jobject jniGetReferent(C_JNIEnv* env, jobject ref) { JNIEnv* e = reinterpret_cast(env); JniConstants::init(e); static jmethodID get = e->GetMethodID(JniConstants::referenceClass, "get", "()Ljava/lang/Object;"); return (*env)->CallObjectMethod(e, ref, get); } jstring jniCreateString(C_JNIEnv* env, const jchar* unicodeChars, jsize len) { JNIEnv* e = reinterpret_cast(env); return (*env)->NewString(e, unicodeChars, len); } JniConstants.cpp0100644 0000000 0000000 00000013743 13277516016 012746 0ustar000000000 0000000 /* * Copyright (C) 2010 The Android Open Source Project * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ #define LOG_TAG "JniConstants" #include "ALog-priv.h" #include "JniConstants.h" #include "ScopedLocalRef.h" #include #include #include static std::atomic g_constants_initialized(false); static std::mutex g_constants_mutex; jclass JniConstants::booleanClass; jclass JniConstants::byteArrayClass; jclass JniConstants::calendarClass; jclass JniConstants::charsetICUClass; jclass JniConstants::doubleClass; jclass JniConstants::errnoExceptionClass; jclass JniConstants::fileDescriptorClass; jclass JniConstants::gaiExceptionClass; jclass JniConstants::inet6AddressClass; jclass JniConstants::inet6AddressHolderClass; jclass JniConstants::inetAddressClass; jclass JniConstants::inetAddressHolderClass; jclass JniConstants::inetSocketAddressClass; jclass JniConstants::inetSocketAddressHolderClass; jclass JniConstants::integerClass; jclass JniConstants::localeDataClass; jclass JniConstants::longClass; jclass JniConstants::mutableIntClass; jclass JniConstants::mutableLongClass; jclass JniConstants::netlinkSocketAddressClass; jclass JniConstants::packetSocketAddressClass; jclass JniConstants::patternSyntaxExceptionClass; jclass JniConstants::referenceClass; jclass JniConstants::socketTaggerClass; jclass JniConstants::stringClass; jclass JniConstants::structAddrinfoClass; jclass JniConstants::structFlockClass; jclass JniConstants::structGroupReqClass; jclass JniConstants::structGroupSourceReqClass; jclass JniConstants::structIfaddrs; jclass JniConstants::structLingerClass; jclass JniConstants::structPasswdClass; jclass JniConstants::structPollfdClass; jclass JniConstants::structStatClass; jclass JniConstants::structStatVfsClass; jclass JniConstants::structTimevalClass; jclass JniConstants::structTimespecClass; jclass JniConstants::structUcredClass; jclass JniConstants::structUtsnameClass; jclass JniConstants::unixSocketAddressClass; jclass JniConstants::zipEntryClass; static jclass findClass(JNIEnv* env, const char* name) { ScopedLocalRef localClass(env, env->FindClass(name)); jclass result = reinterpret_cast(env->NewGlobalRef(localClass.get())); if (result == NULL) { ALOGE("failed to find class '%s'", name); abort(); } return result; } void JniConstants::init(JNIEnv* env) { // Fast check if (g_constants_initialized) { // already initialized return; } // Slightly slower check std::lock_guard guard(g_constants_mutex); if (g_constants_initialized) { // already initialized return; } booleanClass = findClass(env, "java/lang/Boolean"); byteArrayClass = findClass(env, "[B"); calendarClass = findClass(env, "java/util/Calendar"); charsetICUClass = findClass(env, "java/nio/charset/CharsetICU"); doubleClass = findClass(env, "java/lang/Double"); errnoExceptionClass = findClass(env, "android/system/ErrnoException"); fileDescriptorClass = findClass(env, "java/io/FileDescriptor"); gaiExceptionClass = findClass(env, "android/system/GaiException"); inet6AddressClass = findClass(env, "java/net/Inet6Address"); inet6AddressHolderClass = findClass(env, "java/net/Inet6Address$Inet6AddressHolder"); inetAddressClass = findClass(env, "java/net/InetAddress"); inetAddressHolderClass = findClass(env, "java/net/InetAddress$InetAddressHolder"); inetSocketAddressClass = findClass(env, "java/net/InetSocketAddress"); inetSocketAddressHolderClass = findClass(env, "java/net/InetSocketAddress$InetSocketAddressHolder"); integerClass = findClass(env, "java/lang/Integer"); localeDataClass = findClass(env, "libcore/icu/LocaleData"); longClass = findClass(env, "java/lang/Long"); mutableIntClass = findClass(env, "android/util/MutableInt"); mutableLongClass = findClass(env, "android/util/MutableLong"); netlinkSocketAddressClass = findClass(env, "android/system/NetlinkSocketAddress"); packetSocketAddressClass = findClass(env, "android/system/PacketSocketAddress"); patternSyntaxExceptionClass = findClass(env, "java/util/regex/PatternSyntaxException"); referenceClass = findClass(env, "java/lang/ref/Reference"); socketTaggerClass = findClass(env, "dalvik/system/SocketTagger"); stringClass = findClass(env, "java/lang/String"); structAddrinfoClass = findClass(env, "android/system/StructAddrinfo"); structFlockClass = findClass(env, "android/system/StructFlock"); structGroupReqClass = findClass(env, "android/system/StructGroupReq"); structGroupSourceReqClass = findClass(env, "android/system/StructGroupSourceReq"); structIfaddrs = findClass(env, "android/system/StructIfaddrs"); structLingerClass = findClass(env, "android/system/StructLinger"); structPasswdClass = findClass(env, "android/system/StructPasswd"); structPollfdClass = findClass(env, "android/system/StructPollfd"); structStatClass = findClass(env, "android/system/StructStat"); structStatVfsClass = findClass(env, "android/system/StructStatVfs"); structTimevalClass = findClass(env, "android/system/StructTimeval"); structTimespecClass = findClass(env, "android/system/StructTimespec"); structUcredClass = findClass(env, "android/system/StructUcred"); structUtsnameClass = findClass(env, "android/system/StructUtsname"); unixSocketAddressClass = findClass(env, "android/system/UnixSocketAddress"); zipEntryClass = findClass(env, "java/util/zip/ZipEntry"); g_constants_initialized = true; } JniInvocation.cpp0100644 0000000 0000000 00000013452 13277516016 013100 0ustar000000000 0000000 /* * Copyright (C) 2013 The Android Open Source Project * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ #include "JniInvocation.h" #include #include #include #include #define LOG_TAG "JniInvocation" #include "cutils/log.h" #ifdef __ANDROID__ #include #endif JniInvocation* JniInvocation::jni_invocation_ = NULL; JniInvocation::JniInvocation() : handle_(NULL), JNI_GetDefaultJavaVMInitArgs_(NULL), JNI_CreateJavaVM_(NULL), JNI_GetCreatedJavaVMs_(NULL) { LOG_ALWAYS_FATAL_IF(jni_invocation_ != NULL, "JniInvocation instance already initialized"); jni_invocation_ = this; } JniInvocation::~JniInvocation() { jni_invocation_ = NULL; if (handle_ != NULL) { dlclose(handle_); } } #ifdef __ANDROID__ static const char* kLibrarySystemProperty = "persist.sys.dalvik.vm.lib.2"; static const char* kDebuggableSystemProperty = "ro.debuggable"; #endif static const char* kLibraryFallback = "libart.so"; template void UNUSED(const T&) {} const char* JniInvocation::GetLibrary(const char* library, char* buffer) { #ifdef __ANDROID__ const char* default_library; char debuggable[PROP_VALUE_MAX]; __system_property_get(kDebuggableSystemProperty, debuggable); if (strcmp(debuggable, "1") != 0) { // Not a debuggable build. // Do not allow arbitrary library. Ignore the library parameter. This // will also ignore the default library, but initialize to fallback // for cleanliness. library = kLibraryFallback; default_library = kLibraryFallback; } else { // Debuggable build. // Accept the library parameter. For the case it is NULL, load the default // library from the system property. if (buffer != NULL) { if (__system_property_get(kLibrarySystemProperty, buffer) > 0) { default_library = buffer; } else { default_library = kLibraryFallback; } } else { // No buffer given, just use default fallback. default_library = kLibraryFallback; } } #else UNUSED(buffer); const char* default_library = kLibraryFallback; #endif if (library == NULL) { library = default_library; } return library; } bool JniInvocation::Init(const char* library) { #ifdef __ANDROID__ char buffer[PROP_VALUE_MAX]; #else char* buffer = NULL; #endif library = GetLibrary(library, buffer); // Load with RTLD_NODELETE in order to ensure that libart.so is not unmapped when it is closed. // This is due to the fact that it is possible that some threads might have yet to finish // exiting even after JNI_DeleteJavaVM returns, which can lead to segfaults if the library is // unloaded. const int kDlopenFlags = RTLD_NOW | RTLD_NODELETE; handle_ = dlopen(library, kDlopenFlags); if (handle_ == NULL) { if (strcmp(library, kLibraryFallback) == 0) { // Nothing else to try. ALOGE("Failed to dlopen %s: %s", library, dlerror()); return false; } // Note that this is enough to get something like the zygote // running, we can't property_set here to fix this for the future // because we are root and not the system user. See // RuntimeInit.commonInit for where we fix up the property to // avoid future fallbacks. http://b/11463182 ALOGW("Falling back from %s to %s after dlopen error: %s", library, kLibraryFallback, dlerror()); library = kLibraryFallback; handle_ = dlopen(library, kDlopenFlags); if (handle_ == NULL) { ALOGE("Failed to dlopen %s: %s", library, dlerror()); return false; } } if (!FindSymbol(reinterpret_cast(&JNI_GetDefaultJavaVMInitArgs_), "JNI_GetDefaultJavaVMInitArgs")) { return false; } if (!FindSymbol(reinterpret_cast(&JNI_CreateJavaVM_), "JNI_CreateJavaVM")) { return false; } if (!FindSymbol(reinterpret_cast(&JNI_GetCreatedJavaVMs_), "JNI_GetCreatedJavaVMs")) { return false; } return true; } jint JniInvocation::JNI_GetDefaultJavaVMInitArgs(void* vmargs) { return JNI_GetDefaultJavaVMInitArgs_(vmargs); } jint JniInvocation::JNI_CreateJavaVM(JavaVM** p_vm, JNIEnv** p_env, void* vm_args) { return JNI_CreateJavaVM_(p_vm, p_env, vm_args); } jint JniInvocation::JNI_GetCreatedJavaVMs(JavaVM** vms, jsize size, jsize* vm_count) { return JNI_GetCreatedJavaVMs_(vms, size, vm_count); } bool JniInvocation::FindSymbol(void** pointer, const char* symbol) { *pointer = dlsym(handle_, symbol); if (*pointer == NULL) { ALOGE("Failed to find symbol %s: %s\n", symbol, dlerror()); dlclose(handle_); handle_ = NULL; return false; } return true; } JniInvocation& JniInvocation::GetJniInvocation() { LOG_ALWAYS_FATAL_IF(jni_invocation_ == NULL, "Failed to create JniInvocation instance before using JNI invocation API"); return *jni_invocation_; } extern "C" jint JNI_GetDefaultJavaVMInitArgs(void* vm_args) { return JniInvocation::GetJniInvocation().JNI_GetDefaultJavaVMInitArgs(vm_args); } extern "C" jint JNI_CreateJavaVM(JavaVM** p_vm, JNIEnv** p_env, void* vm_args) { return JniInvocation::GetJniInvocation().JNI_CreateJavaVM(p_vm, p_env, vm_args); } extern "C" jint JNI_GetCreatedJavaVMs(JavaVM** vms, jsize size, jsize* vm_count) { return JniInvocation::GetJniInvocation().JNI_GetCreatedJavaVMs(vms, size, vm_count); } MODULE_LICENSE_APACHE20100644 0000000 0000000 00000000000 13277516016 012740 0ustar000000000 0000000 NOTICE0100644 0000000 0000000 00000024707 13277516016 010533 0ustar000000000 0000000 Copyright (c) 2005-2008, The Android Open Source Project Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with the License. Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the specific language governing permissions and limitations under the License. Apache License Version 2.0, January 2004 http://www.apache.org/licenses/ TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION 1. Definitions. "License" shall mean the terms and conditions for use, reproduction, and distribution as defined by Sections 1 through 9 of this document. "Licensor" shall mean the copyright owner or entity authorized by the copyright owner that is granting the License. "Legal Entity" shall mean the union of the acting entity and all other entities that control, are controlled by, or are under common control with that entity. For the purposes of this definition, "control" means (i) the power, direct or indirect, to cause the direction or management of such entity, whether by contract or otherwise, or (ii) ownership of fifty percent (50%) or more of the outstanding shares, or (iii) beneficial ownership of such entity. "You" (or "Your") shall mean an individual or Legal Entity exercising permissions granted by this License. "Source" form shall mean the preferred form for making modifications, including but not limited to software source code, documentation source, and configuration files. "Object" form shall mean any form resulting from mechanical transformation or translation of a Source form, including but not limited to compiled object code, generated documentation, and conversions to other media types. "Work" shall mean the work of authorship, whether in Source or Object form, made available under the License, as indicated by a copyright notice that is included in or attached to the work (an example is provided in the Appendix below). "Derivative Works" shall mean any work, whether in Source or Object form, that is based on (or derived from) the Work and for which the editorial revisions, annotations, elaborations, or other modifications represent, as a whole, an original work of authorship. For the purposes of this License, Derivative Works shall not include works that remain separable from, or merely link (or bind by name) to the interfaces of, the Work and Derivative Works thereof. "Contribution" shall mean any work of authorship, including the original version of the Work and any modifications or additions to that Work or Derivative Works thereof, that is intentionally submitted to Licensor for inclusion in the Work by the copyright owner or by an individual or Legal Entity authorized to submit on behalf of the copyright owner. For the purposes of this definition, "submitted" means any form of electronic, verbal, or written communication sent to the Licensor or its representatives, including but not limited to communication on electronic mailing lists, source code control systems, and issue tracking systems that are managed by, or on behalf of, the Licensor for the purpose of discussing and improving the Work, but excluding communication that is conspicuously marked or otherwise designated in writing by the copyright owner as "Not a Contribution." "Contributor" shall mean Licensor and any individual or Legal Entity on behalf of whom a Contribution has been received by Licensor and subsequently incorporated within the Work. 2. Grant of Copyright License. Subject to the terms and conditions of this License, each Contributor hereby grants to You a perpetual, worldwide, non-exclusive, no-charge, royalty-free, irrevocable copyright license to reproduce, prepare Derivative Works of, publicly display, publicly perform, sublicense, and distribute the Work and such Derivative Works in Source or Object form. 3. Grant of Patent License. Subject to the terms and conditions of this License, each Contributor hereby grants to You a perpetual, worldwide, non-exclusive, no-charge, royalty-free, irrevocable (except as stated in this section) patent license to make, have made, use, offer to sell, sell, import, and otherwise transfer the Work, where such license applies only to those patent claims licensable by such Contributor that are necessarily infringed by their Contribution(s) alone or by combination of their Contribution(s) with the Work to which such Contribution(s) was submitted. If You institute patent litigation against any entity (including a cross-claim or counterclaim in a lawsuit) alleging that the Work or a Contribution incorporated within the Work constitutes direct or contributory patent infringement, then any patent licenses granted to You under this License for that Work shall terminate as of the date such litigation is filed. 4. Redistribution. You may reproduce and distribute copies of the Work or Derivative Works thereof in any medium, with or without modifications, and in Source or Object form, provided that You meet the following conditions: (a) You must give any other recipients of the Work or Derivative Works a copy of this License; and (b) You must cause any modified files to carry prominent notices stating that You changed the files; and (c) You must retain, in the Source form of any Derivative Works that You distribute, all copyright, patent, trademark, and attribution notices from the Source form of the Work, excluding those notices that do not pertain to any part of the Derivative Works; and (d) If the Work includes a "NOTICE" text file as part of its distribution, then any Derivative Works that You distribute must include a readable copy of the attribution notices contained within such NOTICE file, excluding those notices that do not pertain to any part of the Derivative Works, in at least one of the following places: within a NOTICE text file distributed as part of the Derivative Works; within the Source form or documentation, if provided along with the Derivative Works; or, within a display generated by the Derivative Works, if and wherever such third-party notices normally appear. The contents of the NOTICE file are for informational purposes only and do not modify the License. You may add Your own attribution notices within Derivative Works that You distribute, alongside or as an addendum to the NOTICE text from the Work, provided that such additional attribution notices cannot be construed as modifying the License. You may add Your own copyright statement to Your modifications and may provide additional or different license terms and conditions for use, reproduction, or distribution of Your modifications, or for any such Derivative Works as a whole, provided Your use, reproduction, and distribution of the Work otherwise complies with the conditions stated in this License. 5. Submission of Contributions. Unless You explicitly state otherwise, any Contribution intentionally submitted for inclusion in the Work by You to the Licensor shall be under the terms and conditions of this License, without any additional terms or conditions. Notwithstanding the above, nothing herein shall supersede or modify the terms of any separate license agreement you may have executed with Licensor regarding such Contributions. 6. Trademarks. This License does not grant permission to use the trade names, trademarks, service marks, or product names of the Licensor, except as required for reasonable and customary use in describing the origin of the Work and reproducing the content of the NOTICE file. 7. Disclaimer of Warranty. Unless required by applicable law or agreed to in writing, Licensor provides the Work (and each Contributor provides its Contributions) on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied, including, without limitation, any warranties or conditions of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A PARTICULAR PURPOSE. You are solely responsible for determining the appropriateness of using or redistributing the Work and assume any risks associated with Your exercise of permissions under this License. 8. Limitation of Liability. In no event and under no legal theory, whether in tort (including negligence), contract, or otherwise, unless required by applicable law (such as deliberate and grossly negligent acts) or agreed to in writing, shall any Contributor be liable to You for damages, including any direct, indirect, special, incidental, or consequential damages of any character arising as a result of this License or out of the use or inability to use the Work (including but not limited to damages for loss of goodwill, work stoppage, computer failure or malfunction, or any and all other commercial damages or losses), even if such Contributor has been advised of the possibility of such damages. 9. Accepting Warranty or Additional Liability. While redistributing the Work or Derivative Works thereof, You may choose to offer, and charge a fee for, acceptance of support, warranty, indemnity, or other liability obligations and/or rights consistent with this License. However, in accepting such obligations, You may act only on Your own behalf and on Your sole responsibility, not on behalf of any other Contributor, and only if You agree to indemnify, defend, and hold each Contributor harmless for any liability incurred by, or claims asserted against, such Contributor by reason of your accepting any such warranty or additional liability. END OF TERMS AND CONDITIONS README0100644 0000000 0000000 00000000571 13277516016 010500 0ustar000000000 0000000 Support functions for Android's class libraries These are VM-agnostic native functions that implement methods for system class libraries. All code here: - MUST not be associated with an android.* class (that code lives in frameworks/base/). - SHOULD be written in C rather than C++ where possible. Some helper functions are defined in include/nativehelper/JNIHelp.h. include/0040755 0000000 0000000 00000000000 13277516016 011243 5ustar000000000 0000000 include/nativehelper/0040755 0000000 0000000 00000000000 13277516016 013731 5ustar000000000 0000000 include/nativehelper/AsynchronousCloseMonitor.h0100644 0000000 0000000 00000003656 13277516016 021142 0ustar000000000 0000000 /* * Copyright (C) 2010 The Android Open Source Project * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ #ifndef ASYNCHRONOUS_CLOSE_MONITOR_H_included #define ASYNCHRONOUS_CLOSE_MONITOR_H_included #include /** * AsynchronousCloseMonitor helps implement Java's asynchronous close semantics. * * AsynchronousCloseMonitor::init must be called before anything else. * * Every blocking I/O operation must be surrounded by an AsynchronousCloseMonitor * instance. For example: * * { * AsynchronousCloseMonitor monitor(fd); * byteCount = ::read(fd, buf, sizeof(buf)); * } * * To interrupt all threads currently blocked on file descriptor 'fd', call signalBlockedThreads: * * AsynchronousCloseMonitor::signalBlockedThreads(fd); * * To test to see if the interruption was due to the signalBlockedThreads call: * * monitor.wasSignaled(); */ class AsynchronousCloseMonitor { public: explicit AsynchronousCloseMonitor(int fd); ~AsynchronousCloseMonitor(); bool wasSignaled() const; static void init(); static void signalBlockedThreads(int fd); private: AsynchronousCloseMonitor* mPrev; AsynchronousCloseMonitor* mNext; pthread_t mThread; int mFd; bool mSignaled; // Disallow copy and assignment. AsynchronousCloseMonitor(const AsynchronousCloseMonitor&); void operator=(const AsynchronousCloseMonitor&); }; #endif // ASYNCHRONOUS_CLOSE_MONITOR_H_included include/nativehelper/JNIHelp.h0100644 0000000 0000000 00000016120 13277516016 015330 0ustar000000000 0000000 /* * Copyright (C) 2007 The Android Open Source Project * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ /* * JNI helper functions. * * This file may be included by C or C++ code, which is trouble because jni.h * uses different typedefs for JNIEnv in each language. * * TODO: remove C support. */ #ifndef NATIVEHELPER_JNIHELP_H_ #define NATIVEHELPER_JNIHELP_H_ #include "jni.h" #include #include #ifndef NELEM # define NELEM(x) ((int) (sizeof(x) / sizeof((x)[0]))) #endif #ifdef __cplusplus extern "C" { #endif /* * Register one or more native methods with a particular class. * "className" looks like "java/lang/String". Aborts on failure. * TODO: fix all callers and change the return type to void. */ int jniRegisterNativeMethods(C_JNIEnv* env, const char* className, const JNINativeMethod* gMethods, int numMethods); /* * Throw an exception with the specified class and an optional message. * * The "className" argument will be passed directly to FindClass, which * takes strings with slashes (e.g. "java/lang/Object"). * * If an exception is currently pending, we log a warning message and * clear it. * * Returns 0 on success, nonzero if something failed (e.g. the exception * class couldn't be found, so *an* exception will still be pending). * * Currently aborts the VM if it can't throw the exception. */ int jniThrowException(C_JNIEnv* env, const char* className, const char* msg); /* * Throw a java.lang.NullPointerException, with an optional message. */ int jniThrowNullPointerException(C_JNIEnv* env, const char* msg); /* * Throw a java.lang.RuntimeException, with an optional message. */ int jniThrowRuntimeException(C_JNIEnv* env, const char* msg); /* * Throw a java.io.IOException, generating the message from errno. */ int jniThrowIOException(C_JNIEnv* env, int errnum); /* * Return a pointer to a locale-dependent error string explaining errno * value 'errnum'. The returned pointer may or may not be equal to 'buf'. * This function is thread-safe (unlike strerror) and portable (unlike * strerror_r). */ const char* jniStrError(int errnum, char* buf, size_t buflen); /* * Returns a new java.io.FileDescriptor for the given int fd. */ jobject jniCreateFileDescriptor(C_JNIEnv* env, int fd); /* * Returns the int fd from a java.io.FileDescriptor. */ int jniGetFDFromFileDescriptor(C_JNIEnv* env, jobject fileDescriptor); /* * Sets the int fd in a java.io.FileDescriptor. */ void jniSetFileDescriptorOfFD(C_JNIEnv* env, jobject fileDescriptor, int value); /* * Returns the reference from a java.lang.ref.Reference. */ jobject jniGetReferent(C_JNIEnv* env, jobject ref); /* * Returns a Java String object created from UTF-16 data either from jchar or, * if called from C++11, char16_t (a bitwise identical distinct type). */ jstring jniCreateString(C_JNIEnv* env, const jchar* unicodeChars, jsize len); /* * Log a message and an exception. * If exception is NULL, logs the current exception in the JNI environment. */ void jniLogException(C_JNIEnv* env, int priority, const char* tag, jthrowable exception); #ifdef __cplusplus } #endif /* * For C++ code, we provide inlines that map to the C functions. g++ always * inlines these, even on non-optimized builds. */ #if defined(__cplusplus) inline int jniRegisterNativeMethods(JNIEnv* env, const char* className, const JNINativeMethod* gMethods, int numMethods) { return jniRegisterNativeMethods(&env->functions, className, gMethods, numMethods); } inline int jniThrowException(JNIEnv* env, const char* className, const char* msg) { return jniThrowException(&env->functions, className, msg); } extern "C" int jniThrowExceptionFmt(C_JNIEnv* env, const char* className, const char* fmt, va_list args); /* * Equivalent to jniThrowException but with a printf-like format string and * variable-length argument list. This is only available in C++. */ inline int jniThrowExceptionFmt(JNIEnv* env, const char* className, const char* fmt, ...) { va_list args; va_start(args, fmt); return jniThrowExceptionFmt(&env->functions, className, fmt, args); va_end(args); } inline int jniThrowNullPointerException(JNIEnv* env, const char* msg) { return jniThrowNullPointerException(&env->functions, msg); } inline int jniThrowRuntimeException(JNIEnv* env, const char* msg) { return jniThrowRuntimeException(&env->functions, msg); } inline int jniThrowIOException(JNIEnv* env, int errnum) { return jniThrowIOException(&env->functions, errnum); } inline jobject jniCreateFileDescriptor(JNIEnv* env, int fd) { return jniCreateFileDescriptor(&env->functions, fd); } inline int jniGetFDFromFileDescriptor(JNIEnv* env, jobject fileDescriptor) { return jniGetFDFromFileDescriptor(&env->functions, fileDescriptor); } inline void jniSetFileDescriptorOfFD(JNIEnv* env, jobject fileDescriptor, int value) { jniSetFileDescriptorOfFD(&env->functions, fileDescriptor, value); } inline jobject jniGetReferent(JNIEnv* env, jobject ref) { return jniGetReferent(&env->functions, ref); } inline jstring jniCreateString(JNIEnv* env, const jchar* unicodeChars, jsize len) { return jniCreateString(&env->functions, unicodeChars, len); } #if __cplusplus >= 201103L inline jstring jniCreateString(JNIEnv* env, const char16_t* unicodeChars, jsize len) { return jniCreateString(&env->functions, reinterpret_cast(unicodeChars), len); } #endif // __cplusplus >= 201103L inline void jniLogException(JNIEnv* env, int priority, const char* tag, jthrowable exception = NULL) { jniLogException(&env->functions, priority, tag, exception); } #if !defined(DISALLOW_COPY_AND_ASSIGN) // DISALLOW_COPY_AND_ASSIGN disallows the copy and operator= functions. It goes in the private: // declarations in a class. #if __cplusplus >= 201103L #define DISALLOW_COPY_AND_ASSIGN(TypeName) \ TypeName(const TypeName&) = delete; \ void operator=(const TypeName&) = delete #else #define DISALLOW_COPY_AND_ASSIGN(TypeName) \ TypeName(const TypeName&); \ void operator=(const TypeName&) #endif // __has_feature(cxx_deleted_functions) #endif // !defined(DISALLOW_COPY_AND_ASSIGN) #endif /* * TEMP_FAILURE_RETRY is defined by some, but not all, versions of * . (Alas, it is not as standard as we'd hoped!) So, if it's * not already defined, then define it here. */ #ifndef TEMP_FAILURE_RETRY /* Used to retry syscalls that can return EINTR. */ #define TEMP_FAILURE_RETRY(exp) ({ \ typeof (exp) _rc; \ do { \ _rc = (exp); \ } while (_rc == -1 && errno == EINTR); \ _rc; }) #endif #endif /* NATIVEHELPER_JNIHELP_H_ */ include/nativehelper/JniConstants.h0100644 0000000 0000000 00000006670 13277516016 016525 0ustar000000000 0000000 /* * Copyright (C) 2010 The Android Open Source Project * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ #ifndef JNI_CONSTANTS_H_included #define JNI_CONSTANTS_H_included #include "JNIHelp.h" /** * A cache to avoid calling FindClass at runtime. * * Class lookup is relatively expensive, so we do these lookups at startup. This means that code * that never uses, say, java.util.zip.Deflater still has to pay for the lookup, but it means that * on device the cost is paid during boot and amortized. A central cache also removes the temptation * to dynamically call FindClass rather than add a small cache to each file that needs one. Another * cost is that each class cached here requires a global reference, though in practice we save * enough by not having a global reference for each file that uses a class such as java.lang.String * which is used in several files. * * FindClass is still called in a couple of situations: when throwing exceptions, and in some of * the serialization code. The former is clearly not a performance case, and we're currently * assuming that neither is the latter. * * TODO: similar arguments hold for field and method IDs; we should cache them centrally too. */ struct JniConstants { static void init(JNIEnv* env); static jclass booleanClass; static jclass byteArrayClass; static jclass calendarClass; static jclass charsetICUClass; static jclass doubleClass; static jclass errnoExceptionClass; static jclass fileDescriptorClass; static jclass gaiExceptionClass; static jclass inet6AddressClass; static jclass inet6AddressHolderClass; static jclass inetAddressClass; static jclass inetAddressHolderClass; static jclass inetSocketAddressClass; static jclass inetSocketAddressHolderClass; static jclass integerClass; static jclass localeDataClass; static jclass longClass; static jclass mutableIntClass; static jclass mutableLongClass; static jclass netlinkSocketAddressClass; static jclass packetSocketAddressClass; static jclass patternSyntaxExceptionClass; static jclass referenceClass; static jclass socketTaggerClass; static jclass stringClass; static jclass structAddrinfoClass; static jclass structFlockClass; static jclass structGroupReqClass; static jclass structGroupSourceReqClass; static jclass structIfaddrs; static jclass structLingerClass; static jclass structPasswdClass; static jclass structPollfdClass; static jclass structStatClass; static jclass structStatVfsClass; static jclass structTimevalClass; static jclass structTimespecClass; static jclass structUcredClass; static jclass structUtsnameClass; static jclass unixSocketAddressClass; static jclass zipEntryClass; }; #define NATIVE_METHOD(className, functionName, signature) \ { #functionName, signature, reinterpret_cast(className ## _ ## functionName) } #endif // JNI_CONSTANTS_H_included include/nativehelper/JniInvocation.h0100644 0000000 0000000 00000005054 13277516016 016655 0ustar000000000 0000000 /* * Copyright (C) 2013 The Android Open Source Project * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ #ifndef JNI_INVOCATION_H_included #define JNI_INVOCATION_H_included #include // JniInvocation adds a layer of indirection for applications using // the JNI invocation API to allow the JNI implementation to be // selected dynamically. Apps can specify a specific implementation to // be used by calling InitJniInvocation. If this is not done, the // library will chosen based on the value of Android system property // persist.sys.dalvik.vm.lib on the device, and otherwise fall back to // a hard-coded default implementation. class JniInvocation { public: JniInvocation(); ~JniInvocation(); // Initialize JNI invocation API. library should specifiy a valid // shared library for opening via dlopen providing a JNI invocation // implementation, or null to allow defaulting via // persist.sys.dalvik.vm.lib. bool Init(const char* library); // Exposes which library is actually loaded from the given name. The // buffer of size PROPERTY_VALUE_MAX will be used to load the system // property for the default library, if necessary. If no buffer is // provided, the fallback value will be used. static const char* GetLibrary(const char* library, char* buffer); private: bool FindSymbol(void** pointer, const char* symbol); static JniInvocation& GetJniInvocation(); jint JNI_GetDefaultJavaVMInitArgs(void* vmargs); jint JNI_CreateJavaVM(JavaVM** p_vm, JNIEnv** p_env, void* vm_args); jint JNI_GetCreatedJavaVMs(JavaVM** vms, jsize size, jsize* vm_count); static JniInvocation* jni_invocation_; void* handle_; jint (*JNI_GetDefaultJavaVMInitArgs_)(void*); jint (*JNI_CreateJavaVM_)(JavaVM**, JNIEnv**, void*); jint (*JNI_GetCreatedJavaVMs_)(JavaVM**, jsize, jsize*); friend jint JNI_GetDefaultJavaVMInitArgs(void* vm_args); friend jint JNI_CreateJavaVM(JavaVM** p_vm, JNIEnv** p_env, void* vm_args); friend jint JNI_GetCreatedJavaVMs(JavaVM** vms, jsize size, jsize* vm_count); }; #endif // JNI_INVOCATION_H_included include/nativehelper/ScopedBytes.h0100644 0000000 0000000 00000004557 13277516016 016336 0ustar000000000 0000000 /* * Copyright (C) 2010 The Android Open Source Project * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ #ifndef SCOPED_BYTES_H_included #define SCOPED_BYTES_H_included #include "JNIHelp.h" /** * ScopedBytesRO and ScopedBytesRW attempt to paper over the differences between byte[]s and * ByteBuffers. This in turn helps paper over the differences between non-direct ByteBuffers backed * by byte[]s, direct ByteBuffers backed by bytes[]s, and direct ByteBuffers not backed by byte[]s. * (On Android, this last group only contains MappedByteBuffers.) */ template class ScopedBytes { public: ScopedBytes(JNIEnv* env, jobject object) : mEnv(env), mObject(object), mByteArray(NULL), mPtr(NULL) { if (mObject == NULL) { jniThrowNullPointerException(mEnv, NULL); } else if (mEnv->IsInstanceOf(mObject, JniConstants::byteArrayClass)) { mByteArray = reinterpret_cast(mObject); mPtr = mEnv->GetByteArrayElements(mByteArray, NULL); } else { mPtr = reinterpret_cast(mEnv->GetDirectBufferAddress(mObject)); } } ~ScopedBytes() { if (mByteArray != NULL) { mEnv->ReleaseByteArrayElements(mByteArray, mPtr, readOnly ? JNI_ABORT : 0); } } private: JNIEnv* const mEnv; const jobject mObject; jbyteArray mByteArray; protected: jbyte* mPtr; private: DISALLOW_COPY_AND_ASSIGN(ScopedBytes); }; class ScopedBytesRO : public ScopedBytes { public: ScopedBytesRO(JNIEnv* env, jobject object) : ScopedBytes(env, object) {} const jbyte* get() const { return mPtr; } }; class ScopedBytesRW : public ScopedBytes { public: ScopedBytesRW(JNIEnv* env, jobject object) : ScopedBytes(env, object) {} jbyte* get() { return mPtr; } }; #endif // SCOPED_BYTES_H_included include/nativehelper/ScopedLocalFrame.h0100644 0000000 0000000 00000002032 13277516016 017237 0ustar000000000 0000000 /* * Copyright (C) 2010 The Android Open Source Project * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ #ifndef SCOPED_LOCAL_FRAME_H_included #define SCOPED_LOCAL_FRAME_H_included #include "JNIHelp.h" class ScopedLocalFrame { public: explicit ScopedLocalFrame(JNIEnv* env) : mEnv(env) { mEnv->PushLocalFrame(128); } ~ScopedLocalFrame() { mEnv->PopLocalFrame(NULL); } private: JNIEnv* const mEnv; DISALLOW_COPY_AND_ASSIGN(ScopedLocalFrame); }; #endif // SCOPED_LOCAL_FRAME_H_included include/nativehelper/ScopedLocalRef.h0100644 0000000 0000000 00000003101 13277516016 016717 0ustar000000000 0000000 /* * Copyright (C) 2010 The Android Open Source Project * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ #ifndef SCOPED_LOCAL_REF_H_included #define SCOPED_LOCAL_REF_H_included #include "jni.h" #include #include "JNIHelp.h" // for DISALLOW_COPY_AND_ASSIGN. // A smart pointer that deletes a JNI local reference when it goes out of scope. template class ScopedLocalRef { public: ScopedLocalRef(JNIEnv* env, T localRef) : mEnv(env), mLocalRef(localRef) { } ~ScopedLocalRef() { reset(); } void reset(T ptr = NULL) { if (ptr != mLocalRef) { if (mLocalRef != NULL) { mEnv->DeleteLocalRef(mLocalRef); } mLocalRef = ptr; } } T release() __attribute__((warn_unused_result)) { T localRef = mLocalRef; mLocalRef = NULL; return localRef; } T get() const { return mLocalRef; } private: JNIEnv* const mEnv; T mLocalRef; DISALLOW_COPY_AND_ASSIGN(ScopedLocalRef); }; #endif // SCOPED_LOCAL_REF_H_included include/nativehelper/ScopedPrimitiveArray.h0100644 0000000 0000000 00000014145 13277516016 020211 0ustar000000000 0000000 /* * Copyright (C) 2010 The Android Open Source Project * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ #ifndef SCOPED_PRIMITIVE_ARRAY_H_included #define SCOPED_PRIMITIVE_ARRAY_H_included #include "JNIHelp.h" #ifdef POINTER_TYPE #error POINTER_TYPE is defined. #else #define POINTER_TYPE(T) T* /* NOLINT */ #endif #ifdef REFERENCE_TYPE #error REFERENCE_TYPE is defined. #else #define REFERENCE_TYPE(T) T& /* NOLINT */ #endif // ScopedBooleanArrayRO, ScopedByteArrayRO, ScopedCharArrayRO, ScopedDoubleArrayRO, // ScopedFloatArrayRO, ScopedIntArrayRO, ScopedLongArrayRO, and ScopedShortArrayRO provide // convenient read-only access to Java arrays from JNI code. This is cheaper than read-write // access and should be used by default. #define INSTANTIATE_SCOPED_PRIMITIVE_ARRAY_RO(PRIMITIVE_TYPE, NAME) \ class Scoped ## NAME ## ArrayRO { \ public: \ explicit Scoped ## NAME ## ArrayRO(JNIEnv* env) \ : mEnv(env), mJavaArray(NULL), mRawArray(NULL), mSize(0) {} \ Scoped ## NAME ## ArrayRO(JNIEnv* env, PRIMITIVE_TYPE ## Array javaArray) \ : mEnv(env) { \ if (javaArray == NULL) { \ mJavaArray = NULL; \ mSize = 0; \ mRawArray = NULL; \ jniThrowNullPointerException(mEnv, NULL); \ } else { \ reset(javaArray); \ } \ } \ ~Scoped ## NAME ## ArrayRO() { \ if (mRawArray != NULL && mRawArray != mBuffer) { \ mEnv->Release ## NAME ## ArrayElements(mJavaArray, mRawArray, JNI_ABORT); \ } \ } \ void reset(PRIMITIVE_TYPE ## Array javaArray) { \ mJavaArray = javaArray; \ mSize = mEnv->GetArrayLength(mJavaArray); \ if (mSize <= buffer_size) { \ mEnv->Get ## NAME ## ArrayRegion(mJavaArray, 0, mSize, mBuffer); \ mRawArray = mBuffer; \ } else { \ mRawArray = mEnv->Get ## NAME ## ArrayElements(mJavaArray, NULL); \ } \ } \ const PRIMITIVE_TYPE* get() const { return mRawArray; } \ PRIMITIVE_TYPE ## Array getJavaArray() const { return mJavaArray; } \ const PRIMITIVE_TYPE& operator[](size_t n) const { return mRawArray[n]; } \ size_t size() const { return mSize; } \ private: \ static const jsize buffer_size = 1024; \ JNIEnv* const mEnv; \ PRIMITIVE_TYPE ## Array mJavaArray; \ POINTER_TYPE(PRIMITIVE_TYPE) mRawArray; \ jsize mSize; \ PRIMITIVE_TYPE mBuffer[buffer_size]; \ DISALLOW_COPY_AND_ASSIGN(Scoped ## NAME ## ArrayRO); \ } INSTANTIATE_SCOPED_PRIMITIVE_ARRAY_RO(jboolean, Boolean); INSTANTIATE_SCOPED_PRIMITIVE_ARRAY_RO(jbyte, Byte); INSTANTIATE_SCOPED_PRIMITIVE_ARRAY_RO(jchar, Char); INSTANTIATE_SCOPED_PRIMITIVE_ARRAY_RO(jdouble, Double); INSTANTIATE_SCOPED_PRIMITIVE_ARRAY_RO(jfloat, Float); INSTANTIATE_SCOPED_PRIMITIVE_ARRAY_RO(jint, Int); INSTANTIATE_SCOPED_PRIMITIVE_ARRAY_RO(jlong, Long); INSTANTIATE_SCOPED_PRIMITIVE_ARRAY_RO(jshort, Short); #undef INSTANTIATE_SCOPED_PRIMITIVE_ARRAY_RO // ScopedBooleanArrayRW, ScopedByteArrayRW, ScopedCharArrayRW, ScopedDoubleArrayRW, // ScopedFloatArrayRW, ScopedIntArrayRW, ScopedLongArrayRW, and ScopedShortArrayRW provide // convenient read-write access to Java arrays from JNI code. These are more expensive, // since they entail a copy back onto the Java heap, and should only be used when necessary. #define INSTANTIATE_SCOPED_PRIMITIVE_ARRAY_RW(PRIMITIVE_TYPE, NAME) \ class Scoped ## NAME ## ArrayRW { \ public: \ explicit Scoped ## NAME ## ArrayRW(JNIEnv* env) \ : mEnv(env), mJavaArray(NULL), mRawArray(NULL) {} \ Scoped ## NAME ## ArrayRW(JNIEnv* env, PRIMITIVE_TYPE ## Array javaArray) \ : mEnv(env), mJavaArray(javaArray), mRawArray(NULL) { \ if (mJavaArray == NULL) { \ jniThrowNullPointerException(mEnv, NULL); \ } else { \ mRawArray = mEnv->Get ## NAME ## ArrayElements(mJavaArray, NULL); \ } \ } \ ~Scoped ## NAME ## ArrayRW() { \ if (mRawArray) { \ mEnv->Release ## NAME ## ArrayElements(mJavaArray, mRawArray, 0); \ } \ } \ void reset(PRIMITIVE_TYPE ## Array javaArray) { \ mJavaArray = javaArray; \ mRawArray = mEnv->Get ## NAME ## ArrayElements(mJavaArray, NULL); \ } \ const PRIMITIVE_TYPE* get() const { return mRawArray; } \ PRIMITIVE_TYPE ## Array getJavaArray() const { return mJavaArray; } \ const PRIMITIVE_TYPE& operator[](size_t n) const { return mRawArray[n]; } \ POINTER_TYPE(PRIMITIVE_TYPE) get() { return mRawArray; } \ REFERENCE_TYPE(PRIMITIVE_TYPE) operator[](size_t n) { return mRawArray[n]; } \ size_t size() const { return mEnv->GetArrayLength(mJavaArray); } \ private: \ JNIEnv* const mEnv; \ PRIMITIVE_TYPE ## Array mJavaArray; \ POINTER_TYPE(PRIMITIVE_TYPE) mRawArray; \ DISALLOW_COPY_AND_ASSIGN(Scoped ## NAME ## ArrayRW); \ } INSTANTIATE_SCOPED_PRIMITIVE_ARRAY_RW(jboolean, Boolean); INSTANTIATE_SCOPED_PRIMITIVE_ARRAY_RW(jbyte, Byte); INSTANTIATE_SCOPED_PRIMITIVE_ARRAY_RW(jchar, Char); INSTANTIATE_SCOPED_PRIMITIVE_ARRAY_RW(jdouble, Double); INSTANTIATE_SCOPED_PRIMITIVE_ARRAY_RW(jfloat, Float); INSTANTIATE_SCOPED_PRIMITIVE_ARRAY_RW(jint, Int); INSTANTIATE_SCOPED_PRIMITIVE_ARRAY_RW(jlong, Long); INSTANTIATE_SCOPED_PRIMITIVE_ARRAY_RW(jshort, Short); #undef INSTANTIATE_SCOPED_PRIMITIVE_ARRAY_RW #undef POINTER_TYPE #undef REFERENCE_TYPE #endif // SCOPED_PRIMITIVE_ARRAY_H_included include/nativehelper/ScopedStringChars.h0100644 0000000 0000000 00000003565 13277516016 017475 0ustar000000000 0000000 /* * Copyright (C) 2011 The Android Open Source Project * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ #ifndef SCOPED_STRING_CHARS_H_included #define SCOPED_STRING_CHARS_H_included #include "JNIHelp.h" // A smart pointer that provides access to a jchar* given a JNI jstring. // Unlike GetStringChars, we throw NullPointerException rather than abort if // passed a null jstring, and get will return NULL. // This makes the correct idiom very simple: // // ScopedStringChars name(env, java_name); // if (name.get() == NULL) { // return NULL; // } class ScopedStringChars { public: ScopedStringChars(JNIEnv* env, jstring s) : env_(env), string_(s), size_(0) { if (s == NULL) { chars_ = NULL; jniThrowNullPointerException(env, NULL); } else { chars_ = env->GetStringChars(string_, NULL); if (chars_ != NULL) { size_ = env->GetStringLength(string_); } } } ~ScopedStringChars() { if (chars_ != NULL) { env_->ReleaseStringChars(string_, chars_); } } const jchar* get() const { return chars_; } size_t size() const { return size_; } const jchar& operator[](size_t n) const { return chars_[n]; } private: JNIEnv* const env_; const jstring string_; const jchar* chars_; size_t size_; DISALLOW_COPY_AND_ASSIGN(ScopedStringChars); }; #endif // SCOPED_STRING_CHARS_H_included include/nativehelper/ScopedUtfChars.h0100644 0000000 0000000 00000004637 13277516016 016766 0ustar000000000 0000000 /* * Copyright (C) 2010 The Android Open Source Project * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ #ifndef SCOPED_UTF_CHARS_H_included #define SCOPED_UTF_CHARS_H_included #include "JNIHelp.h" #include // A smart pointer that provides read-only access to a Java string's UTF chars. // Unlike GetStringUTFChars, we throw NullPointerException rather than abort if // passed a null jstring, and c_str will return nullptr. // This makes the correct idiom very simple: // // ScopedUtfChars name(env, java_name); // if (name.c_str() == nullptr) { // return nullptr; // } class ScopedUtfChars { public: ScopedUtfChars(JNIEnv* env, jstring s) : env_(env), string_(s) { if (s == nullptr) { utf_chars_ = nullptr; jniThrowNullPointerException(env, nullptr); } else { utf_chars_ = env->GetStringUTFChars(s, nullptr); } } ScopedUtfChars(ScopedUtfChars&& rhs) : env_(rhs.env_), string_(rhs.string_), utf_chars_(rhs.utf_chars_) { rhs.env_ = nullptr; rhs.string_ = nullptr; rhs.utf_chars_ = nullptr; } ~ScopedUtfChars() { if (utf_chars_) { env_->ReleaseStringUTFChars(string_, utf_chars_); } } ScopedUtfChars& operator=(ScopedUtfChars&& rhs) { if (this != &rhs) { // Delete the currently owned UTF chars. this->~ScopedUtfChars(); // Move the rhs ScopedUtfChars and zero it out. env_ = rhs.env_; string_ = rhs.string_; utf_chars_ = rhs.utf_chars_; rhs.env_ = nullptr; rhs.string_ = nullptr; rhs.utf_chars_ = nullptr; } return *this; } const char* c_str() const { return utf_chars_; } size_t size() const { return strlen(utf_chars_); } const char& operator[](size_t n) const { return utf_chars_[n]; } private: JNIEnv* env_; jstring string_; const char* utf_chars_; DISALLOW_COPY_AND_ASSIGN(ScopedUtfChars); }; #endif // SCOPED_UTF_CHARS_H_included include/nativehelper/UniquePtr.h0100644 0000000 0000000 00000012371 13277516016 016037 0ustar000000000 0000000 /* * Copyright (C) 2010 The Android Open Source Project * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ #ifndef UNIQUE_PTR_H_included #define UNIQUE_PTR_H_included #include // For NULL. #include "JNIHelp.h" // For DISALLOW_COPY_AND_ASSIGN. // Default deleter for pointer types. template struct DefaultDelete { enum { type_must_be_complete = sizeof(T) }; DefaultDelete() {} void operator()(T* p) const { delete p; } }; // Default deleter for array types. template struct DefaultDelete { enum { type_must_be_complete = sizeof(T) }; void operator()(T* p) const { delete[] p; } }; // A smart pointer that deletes the given pointer on destruction. // Equivalent to C++0x's std::unique_ptr (a combination of boost::scoped_ptr // and boost::scoped_array). // Named to be in keeping with Android style but also to avoid // collision with any other implementation, until we can switch over // to unique_ptr. // Use thus: // UniquePtr c(new C); template > class UniquePtr { public: // Construct a new UniquePtr, taking ownership of the given raw pointer. explicit UniquePtr(T* ptr = NULL) : mPtr(ptr) { } ~UniquePtr() { reset(); } // Accessors. T& operator*() const { return *mPtr; } T* operator->() const { return mPtr; } T* get() const { return mPtr; } // Returns the raw pointer and hands over ownership to the caller. // The pointer will not be deleted by UniquePtr. T* release() __attribute__((warn_unused_result)) { T* result = mPtr; mPtr = NULL; return result; } // Takes ownership of the given raw pointer. // If this smart pointer previously owned a different raw pointer, that // raw pointer will be freed. void reset(T* ptr = NULL) { if (ptr != mPtr) { D()(mPtr); mPtr = ptr; } } private: // The raw pointer. T* mPtr; // Comparing unique pointers is probably a mistake, since they're unique. template bool operator==(const UniquePtr& p) const; template bool operator!=(const UniquePtr& p) const; DISALLOW_COPY_AND_ASSIGN(UniquePtr); }; // Partial specialization for array types. Like std::unique_ptr, this removes // operator* and operator-> but adds operator[]. template class UniquePtr { public: explicit UniquePtr(T* ptr = NULL) : mPtr(ptr) { } ~UniquePtr() { reset(); } T& operator[](size_t i) const { return mPtr[i]; } T* get() const { return mPtr; } T* release() __attribute__((warn_unused_result)) { T* result = mPtr; mPtr = NULL; return result; } void reset(T* ptr = NULL) { if (ptr != mPtr) { D()(mPtr); mPtr = ptr; } } private: T* mPtr; DISALLOW_COPY_AND_ASSIGN(UniquePtr); }; #if UNIQUE_PTR_TESTS // Run these tests with: // g++ -g -DUNIQUE_PTR_TESTS -x c++ UniquePtr.h && ./a.out #include static void assert(bool b) { if (!b) { fprintf(stderr, "FAIL\n"); abort(); } fprintf(stderr, "OK\n"); } static int cCount = 0; struct C { C() { ++cCount; } ~C() { --cCount; } }; static bool freed = false; struct Freer { void operator()(int* p) { assert(*p == 123); free(p); freed = true; } }; int main(int argc, char* argv[]) { // // UniquePtr tests... // // Can we free a single object? { UniquePtr c(new C); assert(cCount == 1); } assert(cCount == 0); // Does release work? C* rawC; { UniquePtr c(new C); assert(cCount == 1); rawC = c.release(); } assert(cCount == 1); delete rawC; // Does reset work? { UniquePtr c(new C); assert(cCount == 1); c.reset(new C); assert(cCount == 1); } assert(cCount == 0); // // UniquePtr tests... // // Can we free an array? { UniquePtr cs(new C[4]); assert(cCount == 4); } assert(cCount == 0); // Does release work? { UniquePtr c(new C[4]); assert(cCount == 4); rawC = c.release(); } assert(cCount == 4); delete[] rawC; // Does reset work? { UniquePtr c(new C[4]); assert(cCount == 4); c.reset(new C[2]); assert(cCount == 2); } assert(cCount == 0); // // Custom deleter tests... // assert(!freed); { UniquePtr i(reinterpret_cast(malloc(sizeof(int)))); *i = 123; } assert(freed); return 0; } #endif #endif // UNIQUE_PTR_H_included include/nativehelper/toStringArray.h0100644 0000000 0000000 00000004323 13277516016 016711 0ustar000000000 0000000 /* * Copyright (C) 2011 The Android Open Source Project * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ #ifndef TO_STRING_ARRAY_H_included #define TO_STRING_ARRAY_H_included #include "jni.h" #include "ScopedLocalRef.h" #include #include jobjectArray newStringArray(JNIEnv* env, size_t count); template jobjectArray toStringArray(JNIEnv* env, Counter* counter, Getter* getter) { size_t count = (*counter)(); jobjectArray result = newStringArray(env, count); if (result == NULL) { return NULL; } for (size_t i = 0; i < count; ++i) { ScopedLocalRef s(env, env->NewStringUTF((*getter)(i))); if (env->ExceptionCheck()) { return NULL; } env->SetObjectArrayElement(result, i, s.get()); if (env->ExceptionCheck()) { return NULL; } } return result; } struct VectorCounter { const std::vector& strings; explicit VectorCounter(const std::vector& strings) : strings(strings) {} size_t operator()() { return strings.size(); } }; struct VectorGetter { const std::vector& strings; explicit VectorGetter(const std::vector& strings) : strings(strings) {} const char* operator()(size_t i) { return strings[i].c_str(); } }; inline jobjectArray toStringArray(JNIEnv* env, const std::vector& strings) { VectorCounter counter(strings); VectorGetter getter(strings); return toStringArray(env, &counter, &getter); } JNIEXPORT jobjectArray toStringArray(JNIEnv* env, const char* const* strings); #endif // TO_STRING_ARRAY_H_included include_deprecated/0040755 0000000 0000000 00000000000 13277516016 013423 5ustar000000000 0000000 include_deprecated/AsynchronousCloseMonitor.h0100644 0000000 0000000 00000000000 13277516016 032336 2../include/nativehelper/AsynchronousCloseMonitor.hustar000000000 0000000 include_deprecated/JNIHelp.h0100644 0000000 0000000 00000000000 13277516016 022736 2../include/nativehelper/JNIHelp.hustar000000000 0000000 include_deprecated/JniConstants.h0100644 0000000 0000000 00000000000 13277516016 025306 2../include/nativehelper/JniConstants.hustar000000000 0000000 include_deprecated/JniInvocation.h0100644 0000000 0000000 00000000000 13277516016 025600 2../include/nativehelper/JniInvocation.hustar000000000 0000000 include_deprecated/ScopedBytes.h0100644 0000000 0000000 00000000000 13277516016 024724 2../include/nativehelper/ScopedBytes.hustar000000000 0000000 include_deprecated/ScopedLocalFrame.h0100644 0000000 0000000 00000000000 13277516016 026562 2../include/nativehelper/ScopedLocalFrame.hustar000000000 0000000 include_deprecated/ScopedLocalRef.h0100644 0000000 0000000 00000000000 13277516016 025726 2../include/nativehelper/ScopedLocalRef.hustar000000000 0000000 include_deprecated/ScopedPrimitiveArray.h0100644 0000000 0000000 00000000000 13277516016 030466 2../include/nativehelper/ScopedPrimitiveArray.hustar000000000 0000000 include_deprecated/ScopedStringChars.h0100644 0000000 0000000 00000000000 13277516016 027226 2../include/nativehelper/ScopedStringChars.hustar000000000 0000000 include_deprecated/ScopedUtfChars.h0100644 0000000 0000000 00000000000 13277516016 026006 2../include/nativehelper/ScopedUtfChars.hustar000000000 0000000 include_deprecated/UniquePtr.h0100644 0000000 0000000 00000000000 13277516016 024144 2../include/nativehelper/UniquePtr.hustar000000000 0000000 include_deprecated/jni.h0100644 0000000 0000000 00000000000 13277516016 017766 2../include_jni/jni.hustar000000000 0000000 include_deprecated/toStringArray.h0100644 0000000 0000000 00000000000 13277516016 025674 2../include/nativehelper/toStringArray.hustar000000000 0000000 include_jni/0040755 0000000 0000000 00000000000 13277516016 012103 5ustar000000000 0000000 include_jni/jni.h0100644 0000000 0000000 00000145310 13277516016 013035 0ustar000000000 0000000 /* * Copyright (C) 2006 The Android Open Source Project * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ /* * JNI specification, as defined by Sun: * http://java.sun.com/javase/6/docs/technotes/guides/jni/spec/jniTOC.html * * Everything here is expected to be VM-neutral. */ #ifndef JNI_H_ #define JNI_H_ #include #include /* Primitive types that match up with Java equivalents. */ typedef uint8_t jboolean; /* unsigned 8 bits */ typedef int8_t jbyte; /* signed 8 bits */ typedef uint16_t jchar; /* unsigned 16 bits */ typedef int16_t jshort; /* signed 16 bits */ typedef int32_t jint; /* signed 32 bits */ typedef int64_t jlong; /* signed 64 bits */ typedef float jfloat; /* 32-bit IEEE 754 */ typedef double jdouble; /* 64-bit IEEE 754 */ /* "cardinal indices and sizes" */ typedef jint jsize; #ifdef __cplusplus /* * Reference types, in C++ */ class _jobject {}; class _jclass : public _jobject {}; class _jstring : public _jobject {}; class _jarray : public _jobject {}; class _jobjectArray : public _jarray {}; class _jbooleanArray : public _jarray {}; class _jbyteArray : public _jarray {}; class _jcharArray : public _jarray {}; class _jshortArray : public _jarray {}; class _jintArray : public _jarray {}; class _jlongArray : public _jarray {}; class _jfloatArray : public _jarray {}; class _jdoubleArray : public _jarray {}; class _jthrowable : public _jobject {}; typedef _jobject* jobject; typedef _jclass* jclass; typedef _jstring* jstring; typedef _jarray* jarray; typedef _jobjectArray* jobjectArray; typedef _jbooleanArray* jbooleanArray; typedef _jbyteArray* jbyteArray; typedef _jcharArray* jcharArray; typedef _jshortArray* jshortArray; typedef _jintArray* jintArray; typedef _jlongArray* jlongArray; typedef _jfloatArray* jfloatArray; typedef _jdoubleArray* jdoubleArray; typedef _jthrowable* jthrowable; typedef _jobject* jweak; #else /* not __cplusplus */ /* * Reference types, in C. */ typedef void* jobject; typedef jobject jclass; typedef jobject jstring; typedef jobject jarray; typedef jarray jobjectArray; typedef jarray jbooleanArray; typedef jarray jbyteArray; typedef jarray jcharArray; typedef jarray jshortArray; typedef jarray jintArray; typedef jarray jlongArray; typedef jarray jfloatArray; typedef jarray jdoubleArray; typedef jobject jthrowable; typedef jobject jweak; #endif /* not __cplusplus */ struct _jfieldID; /* opaque structure */ typedef struct _jfieldID* jfieldID; /* field IDs */ struct _jmethodID; /* opaque structure */ typedef struct _jmethodID* jmethodID; /* method IDs */ struct JNIInvokeInterface; typedef union jvalue { jboolean z; jbyte b; jchar c; jshort s; jint i; jlong j; jfloat f; jdouble d; jobject l; } jvalue; typedef enum jobjectRefType { JNIInvalidRefType = 0, JNILocalRefType = 1, JNIGlobalRefType = 2, JNIWeakGlobalRefType = 3 } jobjectRefType; typedef struct { const char* name; const char* signature; void* fnPtr; } JNINativeMethod; struct _JNIEnv; struct _JavaVM; typedef const struct JNINativeInterface* C_JNIEnv; #if defined(__cplusplus) typedef _JNIEnv JNIEnv; typedef _JavaVM JavaVM; #else typedef const struct JNINativeInterface* JNIEnv; typedef const struct JNIInvokeInterface* JavaVM; #endif /* * Table of interface function pointers. */ struct JNINativeInterface { void* reserved0; void* reserved1; void* reserved2; void* reserved3; jint (*GetVersion)(JNIEnv *); jclass (*DefineClass)(JNIEnv*, const char*, jobject, const jbyte*, jsize); jclass (*FindClass)(JNIEnv*, const char*); jmethodID (*FromReflectedMethod)(JNIEnv*, jobject); jfieldID (*FromReflectedField)(JNIEnv*, jobject); /* spec doesn't show jboolean parameter */ jobject (*ToReflectedMethod)(JNIEnv*, jclass, jmethodID, jboolean); jclass (*GetSuperclass)(JNIEnv*, jclass); jboolean (*IsAssignableFrom)(JNIEnv*, jclass, jclass); /* spec doesn't show jboolean parameter */ jobject (*ToReflectedField)(JNIEnv*, jclass, jfieldID, jboolean); jint (*Throw)(JNIEnv*, jthrowable); jint (*ThrowNew)(JNIEnv *, jclass, const char *); jthrowable (*ExceptionOccurred)(JNIEnv*); void (*ExceptionDescribe)(JNIEnv*); void (*ExceptionClear)(JNIEnv*); void (*FatalError)(JNIEnv*, const char*); jint (*PushLocalFrame)(JNIEnv*, jint); jobject (*PopLocalFrame)(JNIEnv*, jobject); jobject (*NewGlobalRef)(JNIEnv*, jobject); void (*DeleteGlobalRef)(JNIEnv*, jobject); void (*DeleteLocalRef)(JNIEnv*, jobject); jboolean (*IsSameObject)(JNIEnv*, jobject, jobject); jobject (*NewLocalRef)(JNIEnv*, jobject); jint (*EnsureLocalCapacity)(JNIEnv*, jint); jobject (*AllocObject)(JNIEnv*, jclass); jobject (*NewObject)(JNIEnv*, jclass, jmethodID, ...); jobject (*NewObjectV)(JNIEnv*, jclass, jmethodID, va_list); jobject (*NewObjectA)(JNIEnv*, jclass, jmethodID, jvalue*); jclass (*GetObjectClass)(JNIEnv*, jobject); jboolean (*IsInstanceOf)(JNIEnv*, jobject, jclass); jmethodID (*GetMethodID)(JNIEnv*, jclass, const char*, const char*); jobject (*CallObjectMethod)(JNIEnv*, jobject, jmethodID, ...); jobject (*CallObjectMethodV)(JNIEnv*, jobject, jmethodID, va_list); jobject (*CallObjectMethodA)(JNIEnv*, jobject, jmethodID, jvalue*); jboolean (*CallBooleanMethod)(JNIEnv*, jobject, jmethodID, ...); jboolean (*CallBooleanMethodV)(JNIEnv*, jobject, jmethodID, va_list); jboolean (*CallBooleanMethodA)(JNIEnv*, jobject, jmethodID, jvalue*); jbyte (*CallByteMethod)(JNIEnv*, jobject, jmethodID, ...); jbyte (*CallByteMethodV)(JNIEnv*, jobject, jmethodID, va_list); jbyte (*CallByteMethodA)(JNIEnv*, jobject, jmethodID, jvalue*); jchar (*CallCharMethod)(JNIEnv*, jobject, jmethodID, ...); jchar (*CallCharMethodV)(JNIEnv*, jobject, jmethodID, va_list); jchar (*CallCharMethodA)(JNIEnv*, jobject, jmethodID, jvalue*); jshort (*CallShortMethod)(JNIEnv*, jobject, jmethodID, ...); jshort (*CallShortMethodV)(JNIEnv*, jobject, jmethodID, va_list); jshort (*CallShortMethodA)(JNIEnv*, jobject, jmethodID, jvalue*); jint (*CallIntMethod)(JNIEnv*, jobject, jmethodID, ...); jint (*CallIntMethodV)(JNIEnv*, jobject, jmethodID, va_list); jint (*CallIntMethodA)(JNIEnv*, jobject, jmethodID, jvalue*); jlong (*CallLongMethod)(JNIEnv*, jobject, jmethodID, ...); jlong (*CallLongMethodV)(JNIEnv*, jobject, jmethodID, va_list); jlong (*CallLongMethodA)(JNIEnv*, jobject, jmethodID, jvalue*); jfloat (*CallFloatMethod)(JNIEnv*, jobject, jmethodID, ...); jfloat (*CallFloatMethodV)(JNIEnv*, jobject, jmethodID, va_list); jfloat (*CallFloatMethodA)(JNIEnv*, jobject, jmethodID, jvalue*); jdouble (*CallDoubleMethod)(JNIEnv*, jobject, jmethodID, ...); jdouble (*CallDoubleMethodV)(JNIEnv*, jobject, jmethodID, va_list); jdouble (*CallDoubleMethodA)(JNIEnv*, jobject, jmethodID, jvalue*); void (*CallVoidMethod)(JNIEnv*, jobject, jmethodID, ...); void (*CallVoidMethodV)(JNIEnv*, jobject, jmethodID, va_list); void (*CallVoidMethodA)(JNIEnv*, jobject, jmethodID, jvalue*); jobject (*CallNonvirtualObjectMethod)(JNIEnv*, jobject, jclass, jmethodID, ...); jobject (*CallNonvirtualObjectMethodV)(JNIEnv*, jobject, jclass, jmethodID, va_list); jobject (*CallNonvirtualObjectMethodA)(JNIEnv*, jobject, jclass, jmethodID, jvalue*); jboolean (*CallNonvirtualBooleanMethod)(JNIEnv*, jobject, jclass, jmethodID, ...); jboolean (*CallNonvirtualBooleanMethodV)(JNIEnv*, jobject, jclass, jmethodID, va_list); jboolean (*CallNonvirtualBooleanMethodA)(JNIEnv*, jobject, jclass, jmethodID, jvalue*); jbyte (*CallNonvirtualByteMethod)(JNIEnv*, jobject, jclass, jmethodID, ...); jbyte (*CallNonvirtualByteMethodV)(JNIEnv*, jobject, jclass, jmethodID, va_list); jbyte (*CallNonvirtualByteMethodA)(JNIEnv*, jobject, jclass, jmethodID, jvalue*); jchar (*CallNonvirtualCharMethod)(JNIEnv*, jobject, jclass, jmethodID, ...); jchar (*CallNonvirtualCharMethodV)(JNIEnv*, jobject, jclass, jmethodID, va_list); jchar (*CallNonvirtualCharMethodA)(JNIEnv*, jobject, jclass, jmethodID, jvalue*); jshort (*CallNonvirtualShortMethod)(JNIEnv*, jobject, jclass, jmethodID, ...); jshort (*CallNonvirtualShortMethodV)(JNIEnv*, jobject, jclass, jmethodID, va_list); jshort (*CallNonvirtualShortMethodA)(JNIEnv*, jobject, jclass, jmethodID, jvalue*); jint (*CallNonvirtualIntMethod)(JNIEnv*, jobject, jclass, jmethodID, ...); jint (*CallNonvirtualIntMethodV)(JNIEnv*, jobject, jclass, jmethodID, va_list); jint (*CallNonvirtualIntMethodA)(JNIEnv*, jobject, jclass, jmethodID, jvalue*); jlong (*CallNonvirtualLongMethod)(JNIEnv*, jobject, jclass, jmethodID, ...); jlong (*CallNonvirtualLongMethodV)(JNIEnv*, jobject, jclass, jmethodID, va_list); jlong (*CallNonvirtualLongMethodA)(JNIEnv*, jobject, jclass, jmethodID, jvalue*); jfloat (*CallNonvirtualFloatMethod)(JNIEnv*, jobject, jclass, jmethodID, ...); jfloat (*CallNonvirtualFloatMethodV)(JNIEnv*, jobject, jclass, jmethodID, va_list); jfloat (*CallNonvirtualFloatMethodA)(JNIEnv*, jobject, jclass, jmethodID, jvalue*); jdouble (*CallNonvirtualDoubleMethod)(JNIEnv*, jobject, jclass, jmethodID, ...); jdouble (*CallNonvirtualDoubleMethodV)(JNIEnv*, jobject, jclass, jmethodID, va_list); jdouble (*CallNonvirtualDoubleMethodA)(JNIEnv*, jobject, jclass, jmethodID, jvalue*); void (*CallNonvirtualVoidMethod)(JNIEnv*, jobject, jclass, jmethodID, ...); void (*CallNonvirtualVoidMethodV)(JNIEnv*, jobject, jclass, jmethodID, va_list); void (*CallNonvirtualVoidMethodA)(JNIEnv*, jobject, jclass, jmethodID, jvalue*); jfieldID (*GetFieldID)(JNIEnv*, jclass, const char*, const char*); jobject (*GetObjectField)(JNIEnv*, jobject, jfieldID); jboolean (*GetBooleanField)(JNIEnv*, jobject, jfieldID); jbyte (*GetByteField)(JNIEnv*, jobject, jfieldID); jchar (*GetCharField)(JNIEnv*, jobject, jfieldID); jshort (*GetShortField)(JNIEnv*, jobject, jfieldID); jint (*GetIntField)(JNIEnv*, jobject, jfieldID); jlong (*GetLongField)(JNIEnv*, jobject, jfieldID); jfloat (*GetFloatField)(JNIEnv*, jobject, jfieldID); jdouble (*GetDoubleField)(JNIEnv*, jobject, jfieldID); void (*SetObjectField)(JNIEnv*, jobject, jfieldID, jobject); void (*SetBooleanField)(JNIEnv*, jobject, jfieldID, jboolean); void (*SetByteField)(JNIEnv*, jobject, jfieldID, jbyte); void (*SetCharField)(JNIEnv*, jobject, jfieldID, jchar); void (*SetShortField)(JNIEnv*, jobject, jfieldID, jshort); void (*SetIntField)(JNIEnv*, jobject, jfieldID, jint); void (*SetLongField)(JNIEnv*, jobject, jfieldID, jlong); void (*SetFloatField)(JNIEnv*, jobject, jfieldID, jfloat); void (*SetDoubleField)(JNIEnv*, jobject, jfieldID, jdouble); jmethodID (*GetStaticMethodID)(JNIEnv*, jclass, const char*, const char*); jobject (*CallStaticObjectMethod)(JNIEnv*, jclass, jmethodID, ...); jobject (*CallStaticObjectMethodV)(JNIEnv*, jclass, jmethodID, va_list); jobject (*CallStaticObjectMethodA)(JNIEnv*, jclass, jmethodID, jvalue*); jboolean (*CallStaticBooleanMethod)(JNIEnv*, jclass, jmethodID, ...); jboolean (*CallStaticBooleanMethodV)(JNIEnv*, jclass, jmethodID, va_list); jboolean (*CallStaticBooleanMethodA)(JNIEnv*, jclass, jmethodID, jvalue*); jbyte (*CallStaticByteMethod)(JNIEnv*, jclass, jmethodID, ...); jbyte (*CallStaticByteMethodV)(JNIEnv*, jclass, jmethodID, va_list); jbyte (*CallStaticByteMethodA)(JNIEnv*, jclass, jmethodID, jvalue*); jchar (*CallStaticCharMethod)(JNIEnv*, jclass, jmethodID, ...); jchar (*CallStaticCharMethodV)(JNIEnv*, jclass, jmethodID, va_list); jchar (*CallStaticCharMethodA)(JNIEnv*, jclass, jmethodID, jvalue*); jshort (*CallStaticShortMethod)(JNIEnv*, jclass, jmethodID, ...); jshort (*CallStaticShortMethodV)(JNIEnv*, jclass, jmethodID, va_list); jshort (*CallStaticShortMethodA)(JNIEnv*, jclass, jmethodID, jvalue*); jint (*CallStaticIntMethod)(JNIEnv*, jclass, jmethodID, ...); jint (*CallStaticIntMethodV)(JNIEnv*, jclass, jmethodID, va_list); jint (*CallStaticIntMethodA)(JNIEnv*, jclass, jmethodID, jvalue*); jlong (*CallStaticLongMethod)(JNIEnv*, jclass, jmethodID, ...); jlong (*CallStaticLongMethodV)(JNIEnv*, jclass, jmethodID, va_list); jlong (*CallStaticLongMethodA)(JNIEnv*, jclass, jmethodID, jvalue*); jfloat (*CallStaticFloatMethod)(JNIEnv*, jclass, jmethodID, ...); jfloat (*CallStaticFloatMethodV)(JNIEnv*, jclass, jmethodID, va_list); jfloat (*CallStaticFloatMethodA)(JNIEnv*, jclass, jmethodID, jvalue*); jdouble (*CallStaticDoubleMethod)(JNIEnv*, jclass, jmethodID, ...); jdouble (*CallStaticDoubleMethodV)(JNIEnv*, jclass, jmethodID, va_list); jdouble (*CallStaticDoubleMethodA)(JNIEnv*, jclass, jmethodID, jvalue*); void (*CallStaticVoidMethod)(JNIEnv*, jclass, jmethodID, ...); void (*CallStaticVoidMethodV)(JNIEnv*, jclass, jmethodID, va_list); void (*CallStaticVoidMethodA)(JNIEnv*, jclass, jmethodID, jvalue*); jfieldID (*GetStaticFieldID)(JNIEnv*, jclass, const char*, const char*); jobject (*GetStaticObjectField)(JNIEnv*, jclass, jfieldID); jboolean (*GetStaticBooleanField)(JNIEnv*, jclass, jfieldID); jbyte (*GetStaticByteField)(JNIEnv*, jclass, jfieldID); jchar (*GetStaticCharField)(JNIEnv*, jclass, jfieldID); jshort (*GetStaticShortField)(JNIEnv*, jclass, jfieldID); jint (*GetStaticIntField)(JNIEnv*, jclass, jfieldID); jlong (*GetStaticLongField)(JNIEnv*, jclass, jfieldID); jfloat (*GetStaticFloatField)(JNIEnv*, jclass, jfieldID); jdouble (*GetStaticDoubleField)(JNIEnv*, jclass, jfieldID); void (*SetStaticObjectField)(JNIEnv*, jclass, jfieldID, jobject); void (*SetStaticBooleanField)(JNIEnv*, jclass, jfieldID, jboolean); void (*SetStaticByteField)(JNIEnv*, jclass, jfieldID, jbyte); void (*SetStaticCharField)(JNIEnv*, jclass, jfieldID, jchar); void (*SetStaticShortField)(JNIEnv*, jclass, jfieldID, jshort); void (*SetStaticIntField)(JNIEnv*, jclass, jfieldID, jint); void (*SetStaticLongField)(JNIEnv*, jclass, jfieldID, jlong); void (*SetStaticFloatField)(JNIEnv*, jclass, jfieldID, jfloat); void (*SetStaticDoubleField)(JNIEnv*, jclass, jfieldID, jdouble); jstring (*NewString)(JNIEnv*, const jchar*, jsize); jsize (*GetStringLength)(JNIEnv*, jstring); const jchar* (*GetStringChars)(JNIEnv*, jstring, jboolean*); void (*ReleaseStringChars)(JNIEnv*, jstring, const jchar*); jstring (*NewStringUTF)(JNIEnv*, const char*); jsize (*GetStringUTFLength)(JNIEnv*, jstring); /* JNI spec says this returns const jbyte*, but that's inconsistent */ const char* (*GetStringUTFChars)(JNIEnv*, jstring, jboolean*); void (*ReleaseStringUTFChars)(JNIEnv*, jstring, const char*); jsize (*GetArrayLength)(JNIEnv*, jarray); jobjectArray (*NewObjectArray)(JNIEnv*, jsize, jclass, jobject); jobject (*GetObjectArrayElement)(JNIEnv*, jobjectArray, jsize); void (*SetObjectArrayElement)(JNIEnv*, jobjectArray, jsize, jobject); jbooleanArray (*NewBooleanArray)(JNIEnv*, jsize); jbyteArray (*NewByteArray)(JNIEnv*, jsize); jcharArray (*NewCharArray)(JNIEnv*, jsize); jshortArray (*NewShortArray)(JNIEnv*, jsize); jintArray (*NewIntArray)(JNIEnv*, jsize); jlongArray (*NewLongArray)(JNIEnv*, jsize); jfloatArray (*NewFloatArray)(JNIEnv*, jsize); jdoubleArray (*NewDoubleArray)(JNIEnv*, jsize); jboolean* (*GetBooleanArrayElements)(JNIEnv*, jbooleanArray, jboolean*); jbyte* (*GetByteArrayElements)(JNIEnv*, jbyteArray, jboolean*); jchar* (*GetCharArrayElements)(JNIEnv*, jcharArray, jboolean*); jshort* (*GetShortArrayElements)(JNIEnv*, jshortArray, jboolean*); jint* (*GetIntArrayElements)(JNIEnv*, jintArray, jboolean*); jlong* (*GetLongArrayElements)(JNIEnv*, jlongArray, jboolean*); jfloat* (*GetFloatArrayElements)(JNIEnv*, jfloatArray, jboolean*); jdouble* (*GetDoubleArrayElements)(JNIEnv*, jdoubleArray, jboolean*); void (*ReleaseBooleanArrayElements)(JNIEnv*, jbooleanArray, jboolean*, jint); void (*ReleaseByteArrayElements)(JNIEnv*, jbyteArray, jbyte*, jint); void (*ReleaseCharArrayElements)(JNIEnv*, jcharArray, jchar*, jint); void (*ReleaseShortArrayElements)(JNIEnv*, jshortArray, jshort*, jint); void (*ReleaseIntArrayElements)(JNIEnv*, jintArray, jint*, jint); void (*ReleaseLongArrayElements)(JNIEnv*, jlongArray, jlong*, jint); void (*ReleaseFloatArrayElements)(JNIEnv*, jfloatArray, jfloat*, jint); void (*ReleaseDoubleArrayElements)(JNIEnv*, jdoubleArray, jdouble*, jint); void (*GetBooleanArrayRegion)(JNIEnv*, jbooleanArray, jsize, jsize, jboolean*); void (*GetByteArrayRegion)(JNIEnv*, jbyteArray, jsize, jsize, jbyte*); void (*GetCharArrayRegion)(JNIEnv*, jcharArray, jsize, jsize, jchar*); void (*GetShortArrayRegion)(JNIEnv*, jshortArray, jsize, jsize, jshort*); void (*GetIntArrayRegion)(JNIEnv*, jintArray, jsize, jsize, jint*); void (*GetLongArrayRegion)(JNIEnv*, jlongArray, jsize, jsize, jlong*); void (*GetFloatArrayRegion)(JNIEnv*, jfloatArray, jsize, jsize, jfloat*); void (*GetDoubleArrayRegion)(JNIEnv*, jdoubleArray, jsize, jsize, jdouble*); /* spec shows these without const; some jni.h do, some don't */ void (*SetBooleanArrayRegion)(JNIEnv*, jbooleanArray, jsize, jsize, const jboolean*); void (*SetByteArrayRegion)(JNIEnv*, jbyteArray, jsize, jsize, const jbyte*); void (*SetCharArrayRegion)(JNIEnv*, jcharArray, jsize, jsize, const jchar*); void (*SetShortArrayRegion)(JNIEnv*, jshortArray, jsize, jsize, const jshort*); void (*SetIntArrayRegion)(JNIEnv*, jintArray, jsize, jsize, const jint*); void (*SetLongArrayRegion)(JNIEnv*, jlongArray, jsize, jsize, const jlong*); void (*SetFloatArrayRegion)(JNIEnv*, jfloatArray, jsize, jsize, const jfloat*); void (*SetDoubleArrayRegion)(JNIEnv*, jdoubleArray, jsize, jsize, const jdouble*); jint (*RegisterNatives)(JNIEnv*, jclass, const JNINativeMethod*, jint); jint (*UnregisterNatives)(JNIEnv*, jclass); jint (*MonitorEnter)(JNIEnv*, jobject); jint (*MonitorExit)(JNIEnv*, jobject); jint (*GetJavaVM)(JNIEnv*, JavaVM**); void (*GetStringRegion)(JNIEnv*, jstring, jsize, jsize, jchar*); void (*GetStringUTFRegion)(JNIEnv*, jstring, jsize, jsize, char*); void* (*GetPrimitiveArrayCritical)(JNIEnv*, jarray, jboolean*); void (*ReleasePrimitiveArrayCritical)(JNIEnv*, jarray, void*, jint); const jchar* (*GetStringCritical)(JNIEnv*, jstring, jboolean*); void (*ReleaseStringCritical)(JNIEnv*, jstring, const jchar*); jweak (*NewWeakGlobalRef)(JNIEnv*, jobject); void (*DeleteWeakGlobalRef)(JNIEnv*, jweak); jboolean (*ExceptionCheck)(JNIEnv*); jobject (*NewDirectByteBuffer)(JNIEnv*, void*, jlong); void* (*GetDirectBufferAddress)(JNIEnv*, jobject); jlong (*GetDirectBufferCapacity)(JNIEnv*, jobject); /* added in JNI 1.6 */ jobjectRefType (*GetObjectRefType)(JNIEnv*, jobject); }; /* * C++ object wrapper. * * This is usually overlaid on a C struct whose first element is a * JNINativeInterface*. We rely somewhat on compiler behavior. */ struct _JNIEnv { /* do not rename this; it does not seem to be entirely opaque */ const struct JNINativeInterface* functions; #if defined(__cplusplus) jint GetVersion() { return functions->GetVersion(this); } jclass DefineClass(const char *name, jobject loader, const jbyte* buf, jsize bufLen) { return functions->DefineClass(this, name, loader, buf, bufLen); } jclass FindClass(const char* name) { return functions->FindClass(this, name); } jmethodID FromReflectedMethod(jobject method) { return functions->FromReflectedMethod(this, method); } jfieldID FromReflectedField(jobject field) { return functions->FromReflectedField(this, field); } jobject ToReflectedMethod(jclass cls, jmethodID methodID, jboolean isStatic) { return functions->ToReflectedMethod(this, cls, methodID, isStatic); } jclass GetSuperclass(jclass clazz) { return functions->GetSuperclass(this, clazz); } jboolean IsAssignableFrom(jclass clazz1, jclass clazz2) { return functions->IsAssignableFrom(this, clazz1, clazz2); } jobject ToReflectedField(jclass cls, jfieldID fieldID, jboolean isStatic) { return functions->ToReflectedField(this, cls, fieldID, isStatic); } jint Throw(jthrowable obj) { return functions->Throw(this, obj); } jint ThrowNew(jclass clazz, const char* message) { return functions->ThrowNew(this, clazz, message); } jthrowable ExceptionOccurred() { return functions->ExceptionOccurred(this); } void ExceptionDescribe() { functions->ExceptionDescribe(this); } void ExceptionClear() { functions->ExceptionClear(this); } void FatalError(const char* msg) { functions->FatalError(this, msg); } jint PushLocalFrame(jint capacity) { return functions->PushLocalFrame(this, capacity); } jobject PopLocalFrame(jobject result) { return functions->PopLocalFrame(this, result); } jobject NewGlobalRef(jobject obj) { return functions->NewGlobalRef(this, obj); } void DeleteGlobalRef(jobject globalRef) { functions->DeleteGlobalRef(this, globalRef); } void DeleteLocalRef(jobject localRef) { functions->DeleteLocalRef(this, localRef); } jboolean IsSameObject(jobject ref1, jobject ref2) { return functions->IsSameObject(this, ref1, ref2); } jobject NewLocalRef(jobject ref) { return functions->NewLocalRef(this, ref); } jint EnsureLocalCapacity(jint capacity) { return functions->EnsureLocalCapacity(this, capacity); } jobject AllocObject(jclass clazz) { return functions->AllocObject(this, clazz); } jobject NewObject(jclass clazz, jmethodID methodID, ...) { va_list args; va_start(args, methodID); jobject result = functions->NewObjectV(this, clazz, methodID, args); va_end(args); return result; } jobject NewObjectV(jclass clazz, jmethodID methodID, va_list args) { return functions->NewObjectV(this, clazz, methodID, args); } jobject NewObjectA(jclass clazz, jmethodID methodID, jvalue* args) { return functions->NewObjectA(this, clazz, methodID, args); } jclass GetObjectClass(jobject obj) { return functions->GetObjectClass(this, obj); } jboolean IsInstanceOf(jobject obj, jclass clazz) { return functions->IsInstanceOf(this, obj, clazz); } jmethodID GetMethodID(jclass clazz, const char* name, const char* sig) { return functions->GetMethodID(this, clazz, name, sig); } #define CALL_TYPE_METHOD(_jtype, _jname) \ _jtype Call##_jname##Method(jobject obj, jmethodID methodID, ...) \ { \ _jtype result; \ va_list args; \ va_start(args, methodID); \ result = functions->Call##_jname##MethodV(this, obj, methodID, \ args); \ va_end(args); \ return result; \ } #define CALL_TYPE_METHODV(_jtype, _jname) \ _jtype Call##_jname##MethodV(jobject obj, jmethodID methodID, \ va_list args) \ { return functions->Call##_jname##MethodV(this, obj, methodID, args); } #define CALL_TYPE_METHODA(_jtype, _jname) \ _jtype Call##_jname##MethodA(jobject obj, jmethodID methodID, \ jvalue* args) \ { return functions->Call##_jname##MethodA(this, obj, methodID, args); } #define CALL_TYPE(_jtype, _jname) \ CALL_TYPE_METHOD(_jtype, _jname) \ CALL_TYPE_METHODV(_jtype, _jname) \ CALL_TYPE_METHODA(_jtype, _jname) CALL_TYPE(jobject, Object) CALL_TYPE(jboolean, Boolean) CALL_TYPE(jbyte, Byte) CALL_TYPE(jchar, Char) CALL_TYPE(jshort, Short) CALL_TYPE(jint, Int) CALL_TYPE(jlong, Long) CALL_TYPE(jfloat, Float) CALL_TYPE(jdouble, Double) void CallVoidMethod(jobject obj, jmethodID methodID, ...) { va_list args; va_start(args, methodID); functions->CallVoidMethodV(this, obj, methodID, args); va_end(args); } void CallVoidMethodV(jobject obj, jmethodID methodID, va_list args) { functions->CallVoidMethodV(this, obj, methodID, args); } void CallVoidMethodA(jobject obj, jmethodID methodID, jvalue* args) { functions->CallVoidMethodA(this, obj, methodID, args); } #define CALL_NONVIRT_TYPE_METHOD(_jtype, _jname) \ _jtype CallNonvirtual##_jname##Method(jobject obj, jclass clazz, \ jmethodID methodID, ...) \ { \ _jtype result; \ va_list args; \ va_start(args, methodID); \ result = functions->CallNonvirtual##_jname##MethodV(this, obj, \ clazz, methodID, args); \ va_end(args); \ return result; \ } #define CALL_NONVIRT_TYPE_METHODV(_jtype, _jname) \ _jtype CallNonvirtual##_jname##MethodV(jobject obj, jclass clazz, \ jmethodID methodID, va_list args) \ { return functions->CallNonvirtual##_jname##MethodV(this, obj, clazz, \ methodID, args); } #define CALL_NONVIRT_TYPE_METHODA(_jtype, _jname) \ _jtype CallNonvirtual##_jname##MethodA(jobject obj, jclass clazz, \ jmethodID methodID, jvalue* args) \ { return functions->CallNonvirtual##_jname##MethodA(this, obj, clazz, \ methodID, args); } #define CALL_NONVIRT_TYPE(_jtype, _jname) \ CALL_NONVIRT_TYPE_METHOD(_jtype, _jname) \ CALL_NONVIRT_TYPE_METHODV(_jtype, _jname) \ CALL_NONVIRT_TYPE_METHODA(_jtype, _jname) CALL_NONVIRT_TYPE(jobject, Object) CALL_NONVIRT_TYPE(jboolean, Boolean) CALL_NONVIRT_TYPE(jbyte, Byte) CALL_NONVIRT_TYPE(jchar, Char) CALL_NONVIRT_TYPE(jshort, Short) CALL_NONVIRT_TYPE(jint, Int) CALL_NONVIRT_TYPE(jlong, Long) CALL_NONVIRT_TYPE(jfloat, Float) CALL_NONVIRT_TYPE(jdouble, Double) void CallNonvirtualVoidMethod(jobject obj, jclass clazz, jmethodID methodID, ...) { va_list args; va_start(args, methodID); functions->CallNonvirtualVoidMethodV(this, obj, clazz, methodID, args); va_end(args); } void CallNonvirtualVoidMethodV(jobject obj, jclass clazz, jmethodID methodID, va_list args) { functions->CallNonvirtualVoidMethodV(this, obj, clazz, methodID, args); } void CallNonvirtualVoidMethodA(jobject obj, jclass clazz, jmethodID methodID, jvalue* args) { functions->CallNonvirtualVoidMethodA(this, obj, clazz, methodID, args); } jfieldID GetFieldID(jclass clazz, const char* name, const char* sig) { return functions->GetFieldID(this, clazz, name, sig); } jobject GetObjectField(jobject obj, jfieldID fieldID) { return functions->GetObjectField(this, obj, fieldID); } jboolean GetBooleanField(jobject obj, jfieldID fieldID) { return functions->GetBooleanField(this, obj, fieldID); } jbyte GetByteField(jobject obj, jfieldID fieldID) { return functions->GetByteField(this, obj, fieldID); } jchar GetCharField(jobject obj, jfieldID fieldID) { return functions->GetCharField(this, obj, fieldID); } jshort GetShortField(jobject obj, jfieldID fieldID) { return functions->GetShortField(this, obj, fieldID); } jint GetIntField(jobject obj, jfieldID fieldID) { return functions->GetIntField(this, obj, fieldID); } jlong GetLongField(jobject obj, jfieldID fieldID) { return functions->GetLongField(this, obj, fieldID); } jfloat GetFloatField(jobject obj, jfieldID fieldID) { return functions->GetFloatField(this, obj, fieldID); } jdouble GetDoubleField(jobject obj, jfieldID fieldID) { return functions->GetDoubleField(this, obj, fieldID); } void SetObjectField(jobject obj, jfieldID fieldID, jobject value) { functions->SetObjectField(this, obj, fieldID, value); } void SetBooleanField(jobject obj, jfieldID fieldID, jboolean value) { functions->SetBooleanField(this, obj, fieldID, value); } void SetByteField(jobject obj, jfieldID fieldID, jbyte value) { functions->SetByteField(this, obj, fieldID, value); } void SetCharField(jobject obj, jfieldID fieldID, jchar value) { functions->SetCharField(this, obj, fieldID, value); } void SetShortField(jobject obj, jfieldID fieldID, jshort value) { functions->SetShortField(this, obj, fieldID, value); } void SetIntField(jobject obj, jfieldID fieldID, jint value) { functions->SetIntField(this, obj, fieldID, value); } void SetLongField(jobject obj, jfieldID fieldID, jlong value) { functions->SetLongField(this, obj, fieldID, value); } void SetFloatField(jobject obj, jfieldID fieldID, jfloat value) { functions->SetFloatField(this, obj, fieldID, value); } void SetDoubleField(jobject obj, jfieldID fieldID, jdouble value) { functions->SetDoubleField(this, obj, fieldID, value); } jmethodID GetStaticMethodID(jclass clazz, const char* name, const char* sig) { return functions->GetStaticMethodID(this, clazz, name, sig); } #define CALL_STATIC_TYPE_METHOD(_jtype, _jname) \ _jtype CallStatic##_jname##Method(jclass clazz, jmethodID methodID, \ ...) \ { \ _jtype result; \ va_list args; \ va_start(args, methodID); \ result = functions->CallStatic##_jname##MethodV(this, clazz, \ methodID, args); \ va_end(args); \ return result; \ } #define CALL_STATIC_TYPE_METHODV(_jtype, _jname) \ _jtype CallStatic##_jname##MethodV(jclass clazz, jmethodID methodID, \ va_list args) \ { return functions->CallStatic##_jname##MethodV(this, clazz, methodID, \ args); } #define CALL_STATIC_TYPE_METHODA(_jtype, _jname) \ _jtype CallStatic##_jname##MethodA(jclass clazz, jmethodID methodID, \ jvalue* args) \ { return functions->CallStatic##_jname##MethodA(this, clazz, methodID, \ args); } #define CALL_STATIC_TYPE(_jtype, _jname) \ CALL_STATIC_TYPE_METHOD(_jtype, _jname) \ CALL_STATIC_TYPE_METHODV(_jtype, _jname) \ CALL_STATIC_TYPE_METHODA(_jtype, _jname) CALL_STATIC_TYPE(jobject, Object) CALL_STATIC_TYPE(jboolean, Boolean) CALL_STATIC_TYPE(jbyte, Byte) CALL_STATIC_TYPE(jchar, Char) CALL_STATIC_TYPE(jshort, Short) CALL_STATIC_TYPE(jint, Int) CALL_STATIC_TYPE(jlong, Long) CALL_STATIC_TYPE(jfloat, Float) CALL_STATIC_TYPE(jdouble, Double) void CallStaticVoidMethod(jclass clazz, jmethodID methodID, ...) { va_list args; va_start(args, methodID); functions->CallStaticVoidMethodV(this, clazz, methodID, args); va_end(args); } void CallStaticVoidMethodV(jclass clazz, jmethodID methodID, va_list args) { functions->CallStaticVoidMethodV(this, clazz, methodID, args); } void CallStaticVoidMethodA(jclass clazz, jmethodID methodID, jvalue* args) { functions->CallStaticVoidMethodA(this, clazz, methodID, args); } jfieldID GetStaticFieldID(jclass clazz, const char* name, const char* sig) { return functions->GetStaticFieldID(this, clazz, name, sig); } jobject GetStaticObjectField(jclass clazz, jfieldID fieldID) { return functions->GetStaticObjectField(this, clazz, fieldID); } jboolean GetStaticBooleanField(jclass clazz, jfieldID fieldID) { return functions->GetStaticBooleanField(this, clazz, fieldID); } jbyte GetStaticByteField(jclass clazz, jfieldID fieldID) { return functions->GetStaticByteField(this, clazz, fieldID); } jchar GetStaticCharField(jclass clazz, jfieldID fieldID) { return functions->GetStaticCharField(this, clazz, fieldID); } jshort GetStaticShortField(jclass clazz, jfieldID fieldID) { return functions->GetStaticShortField(this, clazz, fieldID); } jint GetStaticIntField(jclass clazz, jfieldID fieldID) { return functions->GetStaticIntField(this, clazz, fieldID); } jlong GetStaticLongField(jclass clazz, jfieldID fieldID) { return functions->GetStaticLongField(this, clazz, fieldID); } jfloat GetStaticFloatField(jclass clazz, jfieldID fieldID) { return functions->GetStaticFloatField(this, clazz, fieldID); } jdouble GetStaticDoubleField(jclass clazz, jfieldID fieldID) { return functions->GetStaticDoubleField(this, clazz, fieldID); } void SetStaticObjectField(jclass clazz, jfieldID fieldID, jobject value) { functions->SetStaticObjectField(this, clazz, fieldID, value); } void SetStaticBooleanField(jclass clazz, jfieldID fieldID, jboolean value) { functions->SetStaticBooleanField(this, clazz, fieldID, value); } void SetStaticByteField(jclass clazz, jfieldID fieldID, jbyte value) { functions->SetStaticByteField(this, clazz, fieldID, value); } void SetStaticCharField(jclass clazz, jfieldID fieldID, jchar value) { functions->SetStaticCharField(this, clazz, fieldID, value); } void SetStaticShortField(jclass clazz, jfieldID fieldID, jshort value) { functions->SetStaticShortField(this, clazz, fieldID, value); } void SetStaticIntField(jclass clazz, jfieldID fieldID, jint value) { functions->SetStaticIntField(this, clazz, fieldID, value); } void SetStaticLongField(jclass clazz, jfieldID fieldID, jlong value) { functions->SetStaticLongField(this, clazz, fieldID, value); } void SetStaticFloatField(jclass clazz, jfieldID fieldID, jfloat value) { functions->SetStaticFloatField(this, clazz, fieldID, value); } void SetStaticDoubleField(jclass clazz, jfieldID fieldID, jdouble value) { functions->SetStaticDoubleField(this, clazz, fieldID, value); } jstring NewString(const jchar* unicodeChars, jsize len) { return functions->NewString(this, unicodeChars, len); } jsize GetStringLength(jstring string) { return functions->GetStringLength(this, string); } const jchar* GetStringChars(jstring string, jboolean* isCopy) { return functions->GetStringChars(this, string, isCopy); } void ReleaseStringChars(jstring string, const jchar* chars) { functions->ReleaseStringChars(this, string, chars); } jstring NewStringUTF(const char* bytes) { return functions->NewStringUTF(this, bytes); } jsize GetStringUTFLength(jstring string) { return functions->GetStringUTFLength(this, string); } const char* GetStringUTFChars(jstring string, jboolean* isCopy) { return functions->GetStringUTFChars(this, string, isCopy); } void ReleaseStringUTFChars(jstring string, const char* utf) { functions->ReleaseStringUTFChars(this, string, utf); } jsize GetArrayLength(jarray array) { return functions->GetArrayLength(this, array); } jobjectArray NewObjectArray(jsize length, jclass elementClass, jobject initialElement) { return functions->NewObjectArray(this, length, elementClass, initialElement); } jobject GetObjectArrayElement(jobjectArray array, jsize index) { return functions->GetObjectArrayElement(this, array, index); } void SetObjectArrayElement(jobjectArray array, jsize index, jobject value) { functions->SetObjectArrayElement(this, array, index, value); } jbooleanArray NewBooleanArray(jsize length) { return functions->NewBooleanArray(this, length); } jbyteArray NewByteArray(jsize length) { return functions->NewByteArray(this, length); } jcharArray NewCharArray(jsize length) { return functions->NewCharArray(this, length); } jshortArray NewShortArray(jsize length) { return functions->NewShortArray(this, length); } jintArray NewIntArray(jsize length) { return functions->NewIntArray(this, length); } jlongArray NewLongArray(jsize length) { return functions->NewLongArray(this, length); } jfloatArray NewFloatArray(jsize length) { return functions->NewFloatArray(this, length); } jdoubleArray NewDoubleArray(jsize length) { return functions->NewDoubleArray(this, length); } jboolean* GetBooleanArrayElements(jbooleanArray array, jboolean* isCopy) { return functions->GetBooleanArrayElements(this, array, isCopy); } jbyte* GetByteArrayElements(jbyteArray array, jboolean* isCopy) { return functions->GetByteArrayElements(this, array, isCopy); } jchar* GetCharArrayElements(jcharArray array, jboolean* isCopy) { return functions->GetCharArrayElements(this, array, isCopy); } jshort* GetShortArrayElements(jshortArray array, jboolean* isCopy) { return functions->GetShortArrayElements(this, array, isCopy); } jint* GetIntArrayElements(jintArray array, jboolean* isCopy) { return functions->GetIntArrayElements(this, array, isCopy); } jlong* GetLongArrayElements(jlongArray array, jboolean* isCopy) { return functions->GetLongArrayElements(this, array, isCopy); } jfloat* GetFloatArrayElements(jfloatArray array, jboolean* isCopy) { return functions->GetFloatArrayElements(this, array, isCopy); } jdouble* GetDoubleArrayElements(jdoubleArray array, jboolean* isCopy) { return functions->GetDoubleArrayElements(this, array, isCopy); } void ReleaseBooleanArrayElements(jbooleanArray array, jboolean* elems, jint mode) { functions->ReleaseBooleanArrayElements(this, array, elems, mode); } void ReleaseByteArrayElements(jbyteArray array, jbyte* elems, jint mode) { functions->ReleaseByteArrayElements(this, array, elems, mode); } void ReleaseCharArrayElements(jcharArray array, jchar* elems, jint mode) { functions->ReleaseCharArrayElements(this, array, elems, mode); } void ReleaseShortArrayElements(jshortArray array, jshort* elems, jint mode) { functions->ReleaseShortArrayElements(this, array, elems, mode); } void ReleaseIntArrayElements(jintArray array, jint* elems, jint mode) { functions->ReleaseIntArrayElements(this, array, elems, mode); } void ReleaseLongArrayElements(jlongArray array, jlong* elems, jint mode) { functions->ReleaseLongArrayElements(this, array, elems, mode); } void ReleaseFloatArrayElements(jfloatArray array, jfloat* elems, jint mode) { functions->ReleaseFloatArrayElements(this, array, elems, mode); } void ReleaseDoubleArrayElements(jdoubleArray array, jdouble* elems, jint mode) { functions->ReleaseDoubleArrayElements(this, array, elems, mode); } void GetBooleanArrayRegion(jbooleanArray array, jsize start, jsize len, jboolean* buf) { functions->GetBooleanArrayRegion(this, array, start, len, buf); } void GetByteArrayRegion(jbyteArray array, jsize start, jsize len, jbyte* buf) { functions->GetByteArrayRegion(this, array, start, len, buf); } void GetCharArrayRegion(jcharArray array, jsize start, jsize len, jchar* buf) { functions->GetCharArrayRegion(this, array, start, len, buf); } void GetShortArrayRegion(jshortArray array, jsize start, jsize len, jshort* buf) { functions->GetShortArrayRegion(this, array, start, len, buf); } void GetIntArrayRegion(jintArray array, jsize start, jsize len, jint* buf) { functions->GetIntArrayRegion(this, array, start, len, buf); } void GetLongArrayRegion(jlongArray array, jsize start, jsize len, jlong* buf) { functions->GetLongArrayRegion(this, array, start, len, buf); } void GetFloatArrayRegion(jfloatArray array, jsize start, jsize len, jfloat* buf) { functions->GetFloatArrayRegion(this, array, start, len, buf); } void GetDoubleArrayRegion(jdoubleArray array, jsize start, jsize len, jdouble* buf) { functions->GetDoubleArrayRegion(this, array, start, len, buf); } void SetBooleanArrayRegion(jbooleanArray array, jsize start, jsize len, const jboolean* buf) { functions->SetBooleanArrayRegion(this, array, start, len, buf); } void SetByteArrayRegion(jbyteArray array, jsize start, jsize len, const jbyte* buf) { functions->SetByteArrayRegion(this, array, start, len, buf); } void SetCharArrayRegion(jcharArray array, jsize start, jsize len, const jchar* buf) { functions->SetCharArrayRegion(this, array, start, len, buf); } void SetShortArrayRegion(jshortArray array, jsize start, jsize len, const jshort* buf) { functions->SetShortArrayRegion(this, array, start, len, buf); } void SetIntArrayRegion(jintArray array, jsize start, jsize len, const jint* buf) { functions->SetIntArrayRegion(this, array, start, len, buf); } void SetLongArrayRegion(jlongArray array, jsize start, jsize len, const jlong* buf) { functions->SetLongArrayRegion(this, array, start, len, buf); } void SetFloatArrayRegion(jfloatArray array, jsize start, jsize len, const jfloat* buf) { functions->SetFloatArrayRegion(this, array, start, len, buf); } void SetDoubleArrayRegion(jdoubleArray array, jsize start, jsize len, const jdouble* buf) { functions->SetDoubleArrayRegion(this, array, start, len, buf); } jint RegisterNatives(jclass clazz, const JNINativeMethod* methods, jint nMethods) { return functions->RegisterNatives(this, clazz, methods, nMethods); } jint UnregisterNatives(jclass clazz) { return functions->UnregisterNatives(this, clazz); } jint MonitorEnter(jobject obj) { return functions->MonitorEnter(this, obj); } jint MonitorExit(jobject obj) { return functions->MonitorExit(this, obj); } jint GetJavaVM(JavaVM** vm) { return functions->GetJavaVM(this, vm); } void GetStringRegion(jstring str, jsize start, jsize len, jchar* buf) { functions->GetStringRegion(this, str, start, len, buf); } void GetStringUTFRegion(jstring str, jsize start, jsize len, char* buf) { return functions->GetStringUTFRegion(this, str, start, len, buf); } void* GetPrimitiveArrayCritical(jarray array, jboolean* isCopy) { return functions->GetPrimitiveArrayCritical(this, array, isCopy); } void ReleasePrimitiveArrayCritical(jarray array, void* carray, jint mode) { functions->ReleasePrimitiveArrayCritical(this, array, carray, mode); } const jchar* GetStringCritical(jstring string, jboolean* isCopy) { return functions->GetStringCritical(this, string, isCopy); } void ReleaseStringCritical(jstring string, const jchar* carray) { functions->ReleaseStringCritical(this, string, carray); } jweak NewWeakGlobalRef(jobject obj) { return functions->NewWeakGlobalRef(this, obj); } void DeleteWeakGlobalRef(jweak obj) { functions->DeleteWeakGlobalRef(this, obj); } jboolean ExceptionCheck() { return functions->ExceptionCheck(this); } jobject NewDirectByteBuffer(void* address, jlong capacity) { return functions->NewDirectByteBuffer(this, address, capacity); } void* GetDirectBufferAddress(jobject buf) { return functions->GetDirectBufferAddress(this, buf); } jlong GetDirectBufferCapacity(jobject buf) { return functions->GetDirectBufferCapacity(this, buf); } /* added in JNI 1.6 */ jobjectRefType GetObjectRefType(jobject obj) { return functions->GetObjectRefType(this, obj); } #endif /*__cplusplus*/ }; /* * JNI invocation interface. */ struct JNIInvokeInterface { void* reserved0; void* reserved1; void* reserved2; jint (*DestroyJavaVM)(JavaVM*); jint (*AttachCurrentThread)(JavaVM*, JNIEnv**, void*); jint (*DetachCurrentThread)(JavaVM*); jint (*GetEnv)(JavaVM*, void**, jint); jint (*AttachCurrentThreadAsDaemon)(JavaVM*, JNIEnv**, void*); }; /* * C++ version. */ struct _JavaVM { const struct JNIInvokeInterface* functions; #if defined(__cplusplus) jint DestroyJavaVM() { return functions->DestroyJavaVM(this); } jint AttachCurrentThread(JNIEnv** p_env, void* thr_args) { return functions->AttachCurrentThread(this, p_env, thr_args); } jint DetachCurrentThread() { return functions->DetachCurrentThread(this); } jint GetEnv(void** env, jint version) { return functions->GetEnv(this, env, version); } jint AttachCurrentThreadAsDaemon(JNIEnv** p_env, void* thr_args) { return functions->AttachCurrentThreadAsDaemon(this, p_env, thr_args); } #endif /*__cplusplus*/ }; struct JavaVMAttachArgs { jint version; /* must be >= JNI_VERSION_1_2 */ const char* name; /* NULL or name of thread as modified UTF-8 str */ jobject group; /* global ref of a ThreadGroup object, or NULL */ }; typedef struct JavaVMAttachArgs JavaVMAttachArgs; /* * JNI 1.2+ initialization. (As of 1.6, the pre-1.2 structures are no * longer supported.) */ typedef struct JavaVMOption { const char* optionString; void* extraInfo; } JavaVMOption; typedef struct JavaVMInitArgs { jint version; /* use JNI_VERSION_1_2 or later */ jint nOptions; JavaVMOption* options; jboolean ignoreUnrecognized; } JavaVMInitArgs; #ifdef __cplusplus extern "C" { #endif /* * VM initialization functions. * * Note these are the only symbols exported for JNI by the VM. */ jint JNI_GetDefaultJavaVMInitArgs(void*); jint JNI_CreateJavaVM(JavaVM**, JNIEnv**, void*); jint JNI_GetCreatedJavaVMs(JavaVM**, jsize, jsize*); #define JNIIMPORT #define JNIEXPORT __attribute__ ((visibility ("default"))) #define JNICALL /* * Prototypes for functions exported by loadable shared libs. These are * called by JNI, not provided by JNI. */ JNIEXPORT jint JNI_OnLoad(JavaVM* vm, void* reserved); JNIEXPORT void JNI_OnUnload(JavaVM* vm, void* reserved); #ifdef __cplusplus } #endif /* * Manifest constants. */ #define JNI_FALSE 0 #define JNI_TRUE 1 #define JNI_VERSION_1_1 0x00010001 #define JNI_VERSION_1_2 0x00010002 #define JNI_VERSION_1_4 0x00010004 #define JNI_VERSION_1_6 0x00010006 #define JNI_OK (0) /* no error */ #define JNI_ERR (-1) /* generic error */ #define JNI_EDETACHED (-2) /* thread detached from the VM */ #define JNI_EVERSION (-3) /* JNI version error */ #define JNI_COMMIT 1 /* copy content, do not free buffer */ #define JNI_ABORT 2 /* free buffer w/o copying back */ #endif /* JNI_H_ */ platform_include/0040755 0000000 0000000 00000000000 13277516016 013147 5ustar000000000 0000000 platform_include/nativehelper/0040755 0000000 0000000 00000000000 13277516016 015635 5ustar000000000 0000000 platform_include/nativehelper/jni_macros.h0100644 0000000 0000000 00000006167 13277516016 020141 0ustar000000000 0000000 /* * Copyright (C) 2017 The Android Open Source Project * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ /* * JNI helper macros. * * Only intended to be used in the platform. */ #ifndef NATIVEHELPER_JNI_MACROS_H #define NATIVEHELPER_JNI_MACROS_H // Intended to construct a JNINativeMethod. // (Assumes the C name is the ClassName_JavaMethodName). #ifndef NATIVE_METHOD #define NATIVE_METHOD(className, functionName, signature) \ { #functionName, \ signature, \ _NATIVEHELPER_JNI_MACRO_CAST(void*) (className ## _ ## functionName) \ } #endif // Intended to construct a JNINativeMethod (when the C name doesn't match the Java name). // (Assumes the C name is the ClassName_Identifier). #ifndef OVERLOADED_NATIVE_METHOD #define OVERLOADED_NATIVE_METHOD(className, functionName, signature, identifier) \ { #functionName, \ signature, \ _NATIVEHELPER_JNI_MACRO_CAST(void*) (className ## _ ## identifier) \ } #endif // Used for methods that are annotated with @FastNative on the managed side. // See NATIVE_METHOD for usage. #ifndef FAST_NATIVE_METHOD #define FAST_NATIVE_METHOD(className, functionName, signature) \ { #functionName, \ signature, \ _NATIVEHELPER_JNI_MACRO_CAST(void*) (className ## _ ## functionName) \ } #endif // Used for methods that are annotated with @FastNative on the managed side, // and when the C-name doesn't match the Java-name. // // See OVERLOADED_NATIVE_METHOD for usage. #ifndef OVERLOADED_FAST_NATIVE_METHOD #define OVERLOADED_FAST_NATIVE_METHOD(className, functionName, signature, identifier) \ { #functionName, \ signature, \ _NATIVEHELPER_JNI_MACRO_CAST(void*) (className ## _ ## identifier) \ } #endif //////////////////////////////////////////////////////// // IMPLEMENTATION ONLY. // DO NOT USE DIRECTLY. //////////////////////////////////////////////////////// // C-style cast for C, C++-style cast for C++ to avoid warnings/errors. #if defined(__cplusplus) #define _NATIVEHELPER_JNI_MACRO_CAST(to) \ reinterpret_cast #else #define _NATIVEHELPER_JNI_MACRO_CAST(to) \ (to) #endif #endif tests/0040755 0000000 0000000 00000000000 13277516016 010762 5ustar000000000 0000000 tests/Android.bp0100644 0000000 0000000 00000000340 13277516016 012657 0ustar000000000 0000000 // Build the unit tests. cc_test { name: "JniInvocation_test", test_suites: ["device-tests"], host_supported: true, clang: true, srcs: ["JniInvocation_test.cpp"], shared_libs: ["libnativehelper"], } tests/AndroidTest.xml0100644 0000000 0000000 00000002336 13277516016 013725 0ustar000000000 0000000 tests/JniInvocation_test.cpp0100644 0000000 0000000 00000010565 13277516016 015303 0ustar000000000 0000000 /* * Copyright (C) 2014 The Android Open Source Project * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ #define LOG_TAG "NativeBridge_test" #include #include #include "string.h" #if defined(__ANDROID__) && defined(__BIONIC__) #define HAVE_TEST_STUFF 1 #else #undef HAVE_TEST_STUFF #endif #ifdef HAVE_TEST_STUFF // PROPERTY_VALUE_MAX. #include "cutils/properties.h" // Ability to have fake local system properties. #define _REALLY_INCLUDE_SYS__SYSTEM_PROPERTIES_H_ #include struct LocalPropertyTestState { LocalPropertyTestState() : valid(false) { const char* ANDROID_DATA = getenv("ANDROID_DATA"); char dir_template[PATH_MAX]; snprintf(dir_template, sizeof(dir_template), "%s/local/tmp/prop-XXXXXX", ANDROID_DATA); char* dirname = mkdtemp(dir_template); if (!dirname) { fprintf(stderr, "making temp file for test state failed (is %s writable?): %s", dir_template, strerror(errno)); return; } pa_dirname = dirname; pa_filename = pa_dirname + "/__properties__"; __system_property_set_filename(pa_filename.c_str()); __system_property_area_init(); valid = true; } ~LocalPropertyTestState() { if (!valid) { return; } __system_property_set_filename(PROP_FILENAME); __system_properties_init(); unlink(pa_filename.c_str()); rmdir(pa_dirname.c_str()); } public: bool valid; private: std::string pa_dirname; std::string pa_filename; }; #endif namespace android { class JNIInvocationTest : public testing::Test { }; #ifdef HAVE_TEST_STUFF static const char* kDebuggableSystemProperty = "ro.debuggable"; static const char* kIsDebuggableValue = "1"; static const char* kIsNotDebuggableValue = "0"; static const char* kLibrarySystemProperty = "persist.sys.dalvik.vm.lib.2"; static const char* kTestNonNull = "libartd.so"; static const char* kTestNonNull2 = "libartd2.so"; static const char* kExpected = "libart.so"; #endif TEST_F(JNIInvocationTest, Debuggable) { #ifdef HAVE_TEST_STUFF LocalPropertyTestState pa; ASSERT_TRUE(pa.valid); ASSERT_EQ(0, __system_property_add(kDebuggableSystemProperty, 13, kIsDebuggableValue, 1)); ASSERT_EQ(0, __system_property_add(kLibrarySystemProperty, 27, kTestNonNull2, 11)); char buffer[PROPERTY_VALUE_MAX]; const char* result = JniInvocation::GetLibrary(NULL, buffer); EXPECT_FALSE(result == NULL); if (result != NULL) { EXPECT_TRUE(strcmp(result, kTestNonNull2) == 0); EXPECT_FALSE(strcmp(result, kExpected) == 0); } result = JniInvocation::GetLibrary(kTestNonNull, buffer); EXPECT_FALSE(result == NULL); if (result != NULL) { EXPECT_TRUE(strcmp(result, kTestNonNull) == 0); EXPECT_FALSE(strcmp(result, kTestNonNull2) == 0); } #else GTEST_LOG_(WARNING) << "Host testing unsupported. Please run target tests."; #endif } TEST_F(JNIInvocationTest, NonDebuggable) { #ifdef HAVE_TEST_STUFF LocalPropertyTestState pa; ASSERT_TRUE(pa.valid); ASSERT_EQ(0, __system_property_add(kDebuggableSystemProperty, 13, kIsNotDebuggableValue, 1)); char buffer[PROPERTY_VALUE_MAX]; const char* result = JniInvocation::GetLibrary(NULL, buffer); EXPECT_FALSE(result == NULL); if (result != NULL) { EXPECT_TRUE(strcmp(result, kExpected) == 0); EXPECT_FALSE(strcmp(result, kTestNonNull) == 0); EXPECT_FALSE(strcmp(result, kTestNonNull2) == 0); } result = JniInvocation::GetLibrary(kTestNonNull, buffer); EXPECT_FALSE(result == NULL); if (result != NULL) { EXPECT_TRUE(strcmp(result, kExpected) == 0); EXPECT_FALSE(strcmp(result, kTestNonNull) == 0); } #else GTEST_LOG_(WARNING) << "Host testing unsupported. Please run target tests."; #endif } } // namespace android toStringArray.cpp0100644 0000000 0000000 00000002717 13277516016 013140 0ustar000000000 0000000 /* * Copyright (C) 2011 The Android Open Source Project * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ #include "JniConstants.h" #include "toStringArray.h" jobjectArray newStringArray(JNIEnv* env, size_t count) { return env->NewObjectArray(count, JniConstants::stringClass, NULL); } struct ArrayCounter { const char* const* strings; explicit ArrayCounter(const char* const* strings) : strings(strings) {} size_t operator()() { size_t count = 0; while (strings[count] != NULL) { ++count; } return count; } }; struct ArrayGetter { const char* const* strings; explicit ArrayGetter(const char* const* strings) : strings(strings) {} const char* operator()(size_t i) { return strings[i]; } }; jobjectArray toStringArray(JNIEnv* env, const char* const* strings) { ArrayCounter counter(strings); ArrayGetter getter(strings); return toStringArray(env, &counter, &getter); }