13e46e4ee56c8e37158f46941dedd5b436d724baaKenny Root/*
23e46e4ee56c8e37158f46941dedd5b436d724baaKenny Root * Copyright (C) 2007 The Android Open Source Project
33e46e4ee56c8e37158f46941dedd5b436d724baaKenny Root *
43e46e4ee56c8e37158f46941dedd5b436d724baaKenny Root * Licensed under the Apache License, Version 2.0 (the "License");
53e46e4ee56c8e37158f46941dedd5b436d724baaKenny Root * you may not use this file except in compliance with the License.
63e46e4ee56c8e37158f46941dedd5b436d724baaKenny Root * You may obtain a copy of the License at
73e46e4ee56c8e37158f46941dedd5b436d724baaKenny Root *
83e46e4ee56c8e37158f46941dedd5b436d724baaKenny Root *      http://www.apache.org/licenses/LICENSE-2.0
93e46e4ee56c8e37158f46941dedd5b436d724baaKenny Root *
103e46e4ee56c8e37158f46941dedd5b436d724baaKenny Root * Unless required by applicable law or agreed to in writing, software
113e46e4ee56c8e37158f46941dedd5b436d724baaKenny Root * distributed under the License is distributed on an "AS IS" BASIS,
123e46e4ee56c8e37158f46941dedd5b436d724baaKenny Root * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
133e46e4ee56c8e37158f46941dedd5b436d724baaKenny Root * See the License for the specific language governing permissions and
143e46e4ee56c8e37158f46941dedd5b436d724baaKenny Root * limitations under the License.
153e46e4ee56c8e37158f46941dedd5b436d724baaKenny Root */
163e46e4ee56c8e37158f46941dedd5b436d724baaKenny Root
173e46e4ee56c8e37158f46941dedd5b436d724baaKenny Root/*
183e46e4ee56c8e37158f46941dedd5b436d724baaKenny Root * JNI helper functions.
193e46e4ee56c8e37158f46941dedd5b436d724baaKenny Root *
203e46e4ee56c8e37158f46941dedd5b436d724baaKenny Root * This file may be included by C or C++ code, which is trouble because jni.h
213e46e4ee56c8e37158f46941dedd5b436d724baaKenny Root * uses different typedefs for JNIEnv in each language.
223e46e4ee56c8e37158f46941dedd5b436d724baaKenny Root *
233e46e4ee56c8e37158f46941dedd5b436d724baaKenny Root * TODO: remove C support.
243e46e4ee56c8e37158f46941dedd5b436d724baaKenny Root */
253e46e4ee56c8e37158f46941dedd5b436d724baaKenny Root#ifndef NATIVEHELPER_JNIHELP_H_
263e46e4ee56c8e37158f46941dedd5b436d724baaKenny Root#define NATIVEHELPER_JNIHELP_H_
273e46e4ee56c8e37158f46941dedd5b436d724baaKenny Root
283e46e4ee56c8e37158f46941dedd5b436d724baaKenny Root#include "jni.h"
293e46e4ee56c8e37158f46941dedd5b436d724baaKenny Root#include <errno.h>
303e46e4ee56c8e37158f46941dedd5b436d724baaKenny Root#include <unistd.h>
313e46e4ee56c8e37158f46941dedd5b436d724baaKenny Root
323e46e4ee56c8e37158f46941dedd5b436d724baaKenny Root#ifndef NELEM
333e46e4ee56c8e37158f46941dedd5b436d724baaKenny Root# define NELEM(x) ((int) (sizeof(x) / sizeof((x)[0])))
343e46e4ee56c8e37158f46941dedd5b436d724baaKenny Root#endif
353e46e4ee56c8e37158f46941dedd5b436d724baaKenny Root
363e46e4ee56c8e37158f46941dedd5b436d724baaKenny Root#ifdef __cplusplus
373e46e4ee56c8e37158f46941dedd5b436d724baaKenny Rootextern "C" {
383e46e4ee56c8e37158f46941dedd5b436d724baaKenny Root#endif
393e46e4ee56c8e37158f46941dedd5b436d724baaKenny Root
403e46e4ee56c8e37158f46941dedd5b436d724baaKenny Root/*
413e46e4ee56c8e37158f46941dedd5b436d724baaKenny Root * Register one or more native methods with a particular class.
423e46e4ee56c8e37158f46941dedd5b436d724baaKenny Root * "className" looks like "java/lang/String". Aborts on failure.
433e46e4ee56c8e37158f46941dedd5b436d724baaKenny Root * TODO: fix all callers and change the return type to void.
443e46e4ee56c8e37158f46941dedd5b436d724baaKenny Root */
453e46e4ee56c8e37158f46941dedd5b436d724baaKenny Rootint jniRegisterNativeMethods(C_JNIEnv* env, const char* className, const JNINativeMethod* gMethods, int numMethods);
463e46e4ee56c8e37158f46941dedd5b436d724baaKenny Root
473e46e4ee56c8e37158f46941dedd5b436d724baaKenny Root/*
483e46e4ee56c8e37158f46941dedd5b436d724baaKenny Root * Throw an exception with the specified class and an optional message.
493e46e4ee56c8e37158f46941dedd5b436d724baaKenny Root *
503e46e4ee56c8e37158f46941dedd5b436d724baaKenny Root * The "className" argument will be passed directly to FindClass, which
513e46e4ee56c8e37158f46941dedd5b436d724baaKenny Root * takes strings with slashes (e.g. "java/lang/Object").
523e46e4ee56c8e37158f46941dedd5b436d724baaKenny Root *
533e46e4ee56c8e37158f46941dedd5b436d724baaKenny Root * If an exception is currently pending, we log a warning message and
543e46e4ee56c8e37158f46941dedd5b436d724baaKenny Root * clear it.
553e46e4ee56c8e37158f46941dedd5b436d724baaKenny Root *
563e46e4ee56c8e37158f46941dedd5b436d724baaKenny Root * Returns 0 on success, nonzero if something failed (e.g. the exception
573e46e4ee56c8e37158f46941dedd5b436d724baaKenny Root * class couldn't be found, so *an* exception will still be pending).
583e46e4ee56c8e37158f46941dedd5b436d724baaKenny Root *
593e46e4ee56c8e37158f46941dedd5b436d724baaKenny Root * Currently aborts the VM if it can't throw the exception.
603e46e4ee56c8e37158f46941dedd5b436d724baaKenny Root */
613e46e4ee56c8e37158f46941dedd5b436d724baaKenny Rootint jniThrowException(C_JNIEnv* env, const char* className, const char* msg);
623e46e4ee56c8e37158f46941dedd5b436d724baaKenny Root
633e46e4ee56c8e37158f46941dedd5b436d724baaKenny Root/*
643e46e4ee56c8e37158f46941dedd5b436d724baaKenny Root * Throw a java.lang.NullPointerException, with an optional message.
653e46e4ee56c8e37158f46941dedd5b436d724baaKenny Root */
663e46e4ee56c8e37158f46941dedd5b436d724baaKenny Rootint jniThrowNullPointerException(C_JNIEnv* env, const char* msg);
673e46e4ee56c8e37158f46941dedd5b436d724baaKenny Root
683e46e4ee56c8e37158f46941dedd5b436d724baaKenny Root/*
693e46e4ee56c8e37158f46941dedd5b436d724baaKenny Root * Throw a java.lang.RuntimeException, with an optional message.
703e46e4ee56c8e37158f46941dedd5b436d724baaKenny Root */
713e46e4ee56c8e37158f46941dedd5b436d724baaKenny Rootint jniThrowRuntimeException(C_JNIEnv* env, const char* msg);
723e46e4ee56c8e37158f46941dedd5b436d724baaKenny Root
733e46e4ee56c8e37158f46941dedd5b436d724baaKenny Root/*
743e46e4ee56c8e37158f46941dedd5b436d724baaKenny Root * Throw a java.io.IOException, generating the message from errno.
753e46e4ee56c8e37158f46941dedd5b436d724baaKenny Root */
763e46e4ee56c8e37158f46941dedd5b436d724baaKenny Rootint jniThrowIOException(C_JNIEnv* env, int errnum);
773e46e4ee56c8e37158f46941dedd5b436d724baaKenny Root
783e46e4ee56c8e37158f46941dedd5b436d724baaKenny Root/*
793e46e4ee56c8e37158f46941dedd5b436d724baaKenny Root * Return a pointer to a locale-dependent error string explaining errno
803e46e4ee56c8e37158f46941dedd5b436d724baaKenny Root * value 'errnum'. The returned pointer may or may not be equal to 'buf'.
813e46e4ee56c8e37158f46941dedd5b436d724baaKenny Root * This function is thread-safe (unlike strerror) and portable (unlike
823e46e4ee56c8e37158f46941dedd5b436d724baaKenny Root * strerror_r).
833e46e4ee56c8e37158f46941dedd5b436d724baaKenny Root */
843e46e4ee56c8e37158f46941dedd5b436d724baaKenny Rootconst char* jniStrError(int errnum, char* buf, size_t buflen);
853e46e4ee56c8e37158f46941dedd5b436d724baaKenny Root
863e46e4ee56c8e37158f46941dedd5b436d724baaKenny Root/*
873e46e4ee56c8e37158f46941dedd5b436d724baaKenny Root * Returns a new java.io.FileDescriptor for the given int fd.
883e46e4ee56c8e37158f46941dedd5b436d724baaKenny Root */
893e46e4ee56c8e37158f46941dedd5b436d724baaKenny Rootjobject jniCreateFileDescriptor(C_JNIEnv* env, int fd);
903e46e4ee56c8e37158f46941dedd5b436d724baaKenny Root
913e46e4ee56c8e37158f46941dedd5b436d724baaKenny Root/*
923e46e4ee56c8e37158f46941dedd5b436d724baaKenny Root * Returns the int fd from a java.io.FileDescriptor.
933e46e4ee56c8e37158f46941dedd5b436d724baaKenny Root */
943e46e4ee56c8e37158f46941dedd5b436d724baaKenny Rootint jniGetFDFromFileDescriptor(C_JNIEnv* env, jobject fileDescriptor);
953e46e4ee56c8e37158f46941dedd5b436d724baaKenny Root
963e46e4ee56c8e37158f46941dedd5b436d724baaKenny Root/*
973e46e4ee56c8e37158f46941dedd5b436d724baaKenny Root * Sets the int fd in a java.io.FileDescriptor.
983e46e4ee56c8e37158f46941dedd5b436d724baaKenny Root */
993e46e4ee56c8e37158f46941dedd5b436d724baaKenny Rootvoid jniSetFileDescriptorOfFD(C_JNIEnv* env, jobject fileDescriptor, int value);
1003e46e4ee56c8e37158f46941dedd5b436d724baaKenny Root
1013e46e4ee56c8e37158f46941dedd5b436d724baaKenny Root/*
1023e46e4ee56c8e37158f46941dedd5b436d724baaKenny Root * Returns the reference from a java.lang.ref.Reference.
1033e46e4ee56c8e37158f46941dedd5b436d724baaKenny Root */
1043e46e4ee56c8e37158f46941dedd5b436d724baaKenny Rootjobject jniGetReferent(C_JNIEnv* env, jobject ref);
1053e46e4ee56c8e37158f46941dedd5b436d724baaKenny Root
1063e46e4ee56c8e37158f46941dedd5b436d724baaKenny Root/*
1073e46e4ee56c8e37158f46941dedd5b436d724baaKenny Root * Log a message and an exception.
1083e46e4ee56c8e37158f46941dedd5b436d724baaKenny Root * If exception is NULL, logs the current exception in the JNI environment.
1093e46e4ee56c8e37158f46941dedd5b436d724baaKenny Root */
1103e46e4ee56c8e37158f46941dedd5b436d724baaKenny Rootvoid jniLogException(C_JNIEnv* env, int priority, const char* tag, jthrowable exception);
1113e46e4ee56c8e37158f46941dedd5b436d724baaKenny Root
1123e46e4ee56c8e37158f46941dedd5b436d724baaKenny Root#ifdef __cplusplus
1133e46e4ee56c8e37158f46941dedd5b436d724baaKenny Root}
1143e46e4ee56c8e37158f46941dedd5b436d724baaKenny Root#endif
1153e46e4ee56c8e37158f46941dedd5b436d724baaKenny Root
1163e46e4ee56c8e37158f46941dedd5b436d724baaKenny Root
1173e46e4ee56c8e37158f46941dedd5b436d724baaKenny Root/*
1183e46e4ee56c8e37158f46941dedd5b436d724baaKenny Root * For C++ code, we provide inlines that map to the C functions.  g++ always
1193e46e4ee56c8e37158f46941dedd5b436d724baaKenny Root * inlines these, even on non-optimized builds.
1203e46e4ee56c8e37158f46941dedd5b436d724baaKenny Root */
1213e46e4ee56c8e37158f46941dedd5b436d724baaKenny Root#if defined(__cplusplus)
1223e46e4ee56c8e37158f46941dedd5b436d724baaKenny Rootinline int jniRegisterNativeMethods(JNIEnv* env, const char* className, const JNINativeMethod* gMethods, int numMethods) {
1233e46e4ee56c8e37158f46941dedd5b436d724baaKenny Root    return jniRegisterNativeMethods(&env->functions, className, gMethods, numMethods);
1243e46e4ee56c8e37158f46941dedd5b436d724baaKenny Root}
1253e46e4ee56c8e37158f46941dedd5b436d724baaKenny Root
1263e46e4ee56c8e37158f46941dedd5b436d724baaKenny Rootinline int jniThrowException(JNIEnv* env, const char* className, const char* msg) {
1273e46e4ee56c8e37158f46941dedd5b436d724baaKenny Root    return jniThrowException(&env->functions, className, msg);
1283e46e4ee56c8e37158f46941dedd5b436d724baaKenny Root}
1293e46e4ee56c8e37158f46941dedd5b436d724baaKenny Root
1303e46e4ee56c8e37158f46941dedd5b436d724baaKenny Rootextern "C" int jniThrowExceptionFmt(C_JNIEnv* env, const char* className, const char* fmt, va_list args);
1313e46e4ee56c8e37158f46941dedd5b436d724baaKenny Root
1323e46e4ee56c8e37158f46941dedd5b436d724baaKenny Root/*
1333e46e4ee56c8e37158f46941dedd5b436d724baaKenny Root * Equivalent to jniThrowException but with a printf-like format string and
1343e46e4ee56c8e37158f46941dedd5b436d724baaKenny Root * variable-length argument list. This is only available in C++.
1353e46e4ee56c8e37158f46941dedd5b436d724baaKenny Root */
1363e46e4ee56c8e37158f46941dedd5b436d724baaKenny Rootinline int jniThrowExceptionFmt(JNIEnv* env, const char* className, const char* fmt, ...) {
1373e46e4ee56c8e37158f46941dedd5b436d724baaKenny Root    va_list args;
1383e46e4ee56c8e37158f46941dedd5b436d724baaKenny Root    va_start(args, fmt);
1393e46e4ee56c8e37158f46941dedd5b436d724baaKenny Root    return jniThrowExceptionFmt(&env->functions, className, fmt, args);
1403e46e4ee56c8e37158f46941dedd5b436d724baaKenny Root    va_end(args);
1413e46e4ee56c8e37158f46941dedd5b436d724baaKenny Root}
1423e46e4ee56c8e37158f46941dedd5b436d724baaKenny Root
1433e46e4ee56c8e37158f46941dedd5b436d724baaKenny Rootinline int jniThrowNullPointerException(JNIEnv* env, const char* msg) {
1443e46e4ee56c8e37158f46941dedd5b436d724baaKenny Root    return jniThrowNullPointerException(&env->functions, msg);
1453e46e4ee56c8e37158f46941dedd5b436d724baaKenny Root}
1463e46e4ee56c8e37158f46941dedd5b436d724baaKenny Root
1473e46e4ee56c8e37158f46941dedd5b436d724baaKenny Rootinline int jniThrowRuntimeException(JNIEnv* env, const char* msg) {
1483e46e4ee56c8e37158f46941dedd5b436d724baaKenny Root    return jniThrowRuntimeException(&env->functions, msg);
1493e46e4ee56c8e37158f46941dedd5b436d724baaKenny Root}
1503e46e4ee56c8e37158f46941dedd5b436d724baaKenny Root
1513e46e4ee56c8e37158f46941dedd5b436d724baaKenny Rootinline int jniThrowIOException(JNIEnv* env, int errnum) {
1523e46e4ee56c8e37158f46941dedd5b436d724baaKenny Root    return jniThrowIOException(&env->functions, errnum);
1533e46e4ee56c8e37158f46941dedd5b436d724baaKenny Root}
1543e46e4ee56c8e37158f46941dedd5b436d724baaKenny Root
1553e46e4ee56c8e37158f46941dedd5b436d724baaKenny Rootinline jobject jniCreateFileDescriptor(JNIEnv* env, int fd) {
1563e46e4ee56c8e37158f46941dedd5b436d724baaKenny Root    return jniCreateFileDescriptor(&env->functions, fd);
1573e46e4ee56c8e37158f46941dedd5b436d724baaKenny Root}
1583e46e4ee56c8e37158f46941dedd5b436d724baaKenny Root
1593e46e4ee56c8e37158f46941dedd5b436d724baaKenny Rootinline int jniGetFDFromFileDescriptor(JNIEnv* env, jobject fileDescriptor) {
1603e46e4ee56c8e37158f46941dedd5b436d724baaKenny Root    return jniGetFDFromFileDescriptor(&env->functions, fileDescriptor);
1613e46e4ee56c8e37158f46941dedd5b436d724baaKenny Root}
1623e46e4ee56c8e37158f46941dedd5b436d724baaKenny Root
1633e46e4ee56c8e37158f46941dedd5b436d724baaKenny Rootinline void jniSetFileDescriptorOfFD(JNIEnv* env, jobject fileDescriptor, int value) {
1643e46e4ee56c8e37158f46941dedd5b436d724baaKenny Root    jniSetFileDescriptorOfFD(&env->functions, fileDescriptor, value);
1653e46e4ee56c8e37158f46941dedd5b436d724baaKenny Root}
1663e46e4ee56c8e37158f46941dedd5b436d724baaKenny Root
1673e46e4ee56c8e37158f46941dedd5b436d724baaKenny Rootinline jobject jniGetReferent(JNIEnv* env, jobject ref) {
1683e46e4ee56c8e37158f46941dedd5b436d724baaKenny Root    return jniGetReferent(&env->functions, ref);
1693e46e4ee56c8e37158f46941dedd5b436d724baaKenny Root}
1703e46e4ee56c8e37158f46941dedd5b436d724baaKenny Root
1713e46e4ee56c8e37158f46941dedd5b436d724baaKenny Rootinline void jniLogException(JNIEnv* env, int priority, const char* tag, jthrowable exception = NULL) {
1723e46e4ee56c8e37158f46941dedd5b436d724baaKenny Root    jniLogException(&env->functions, priority, tag, exception);
1733e46e4ee56c8e37158f46941dedd5b436d724baaKenny Root}
1743e46e4ee56c8e37158f46941dedd5b436d724baaKenny Root
1753e46e4ee56c8e37158f46941dedd5b436d724baaKenny Root#endif
1763e46e4ee56c8e37158f46941dedd5b436d724baaKenny Root
1773e46e4ee56c8e37158f46941dedd5b436d724baaKenny Root/*
1783e46e4ee56c8e37158f46941dedd5b436d724baaKenny Root * TEMP_FAILURE_RETRY is defined by some, but not all, versions of
1793e46e4ee56c8e37158f46941dedd5b436d724baaKenny Root * <unistd.h>. (Alas, it is not as standard as we'd hoped!) So, if it's
1803e46e4ee56c8e37158f46941dedd5b436d724baaKenny Root * not already defined, then define it here.
1813e46e4ee56c8e37158f46941dedd5b436d724baaKenny Root */
1823e46e4ee56c8e37158f46941dedd5b436d724baaKenny Root#ifndef TEMP_FAILURE_RETRY
1833e46e4ee56c8e37158f46941dedd5b436d724baaKenny Root/* Used to retry syscalls that can return EINTR. */
1843e46e4ee56c8e37158f46941dedd5b436d724baaKenny Root#define TEMP_FAILURE_RETRY(exp) ({         \
1853e46e4ee56c8e37158f46941dedd5b436d724baaKenny Root    typeof (exp) _rc;                      \
1863e46e4ee56c8e37158f46941dedd5b436d724baaKenny Root    do {                                   \
1873e46e4ee56c8e37158f46941dedd5b436d724baaKenny Root        _rc = (exp);                       \
1883e46e4ee56c8e37158f46941dedd5b436d724baaKenny Root    } while (_rc == -1 && errno == EINTR); \
1893e46e4ee56c8e37158f46941dedd5b436d724baaKenny Root    _rc; })
1903e46e4ee56c8e37158f46941dedd5b436d724baaKenny Root#endif
1913e46e4ee56c8e37158f46941dedd5b436d724baaKenny Root
1923e46e4ee56c8e37158f46941dedd5b436d724baaKenny Root#endif  /* NATIVEHELPER_JNIHELP_H_ */
193