// TODO: are we supposed to support the 'metadata' flag? (false => fdatasync.) static void harmony_io_fflush(JNIEnv* env, jobject, jint fd, jboolean metadata) { int rc = fsync(fd); if (rc == -1) { jniThrowIOException(env, errno); } }
static jint harmony_io_close(JNIEnv* env, jobject, jint fd) { jint rc = TEMP_FAILURE_RETRY(close(fd)); if (rc == -1) { jniThrowIOException(env, errno); } return rc; }
static void socket_bind_local (JNIEnv *env, jobject object, jobject fileDescriptor, jstring name, jint namespaceId) { int ret; int fd; if (name == NULL) { jniThrowNullPointerException(env, NULL); return; } fd = jniGetFDFromFileDescriptor(env, fileDescriptor); if (env->ExceptionCheck()) { return; } ScopedUtfChars nameUtf8(env, name); ret = socket_local_server_bind(fd, nameUtf8.c_str(), namespaceId); if (ret < 0) { jniThrowIOException(env, errno); return; } }
static jlong harmony_io_seek(JNIEnv* env, jobject, jint fd, jlong offset, jint javaWhence) { /* Convert whence argument */ int nativeWhence = 0; switch (javaWhence) { case 1: nativeWhence = SEEK_SET; break; case 2: nativeWhence = SEEK_CUR; break; case 4: nativeWhence = SEEK_END; break; default: return -1; } // If the offset is relative, lseek(2) will tell us whether it's too large. // We're just worried about too large an absolute offset, which would cause // us to lie to lseek(2). if (offsetTooLarge(env, offset)) { return -1; } jlong result = lseek(fd, offset, nativeWhence); if (result == -1) { jniThrowIOException(env, errno); } return result; }
static jint socket_read (JNIEnv *env, jobject object, jobject fileDescriptor) { int fd; int err; if (fileDescriptor == NULL) { jniThrowNullPointerException(env, NULL); return (jint)-1; } fd = jniGetFDFromFileDescriptor(env, fileDescriptor); if (env->ExceptionCheck()) { return (jint)0; } unsigned char buf; err = socket_read_all(env, object, fd, &buf, 1); if (err < 0) { jniThrowIOException(env, errno); return (jint)0; } if (err == 0) { // end of file return (jint)-1; } return (jint)buf; }
/* private native void connectLocal(FileDescriptor fd, * String name, int namespace) throws IOException */ static void socket_connect_local(JNIEnv *env, jobject object, jobject fileDescriptor, jstring name, jint namespaceId) { int ret; int fd; fd = jniGetFDFromFileDescriptor(env, fileDescriptor); if (env->ExceptionCheck()) { return; } ScopedUtfChars nameUtf8(env, name); ret = socket_local_client_connect( fd, nameUtf8.c_str(), namespaceId, SOCK_STREAM); if (ret < 0) { jniThrowIOException(env, errno); return; } }
static jint socket_pending (JNIEnv *env, jobject object, jobject fileDescriptor) { int fd; fd = jniGetFDFromFileDescriptor(env, fileDescriptor); if (env->ExceptionCheck()) { return (jint)-1; } int pending; int ret = ioctl(fd, TIOCOUTQ, &pending); // If this were a non-socket fd, there would be other cases to worry // about... //ALOGD("socket_pending, ioctl ret:%d, pending:%d", ret, pending); if (ret < 0) { jniThrowIOException(env, errno); return (jint) 0; } return (jint)pending; }
static jint socket_getOption(JNIEnv *env, jobject object, jobject fileDescriptor, int optID) { int ret, value; int opt, level; int fd; socklen_t size = sizeof(int); if (!java_opt_to_real(optID, &opt, &level)) { jniThrowIOException(env, -1); return 0; } fd = jniGetFDFromFileDescriptor(env, fileDescriptor); if (env->ExceptionOccurred() != NULL) { return 0; } switch (opt) { case SO_LINGER: { struct linger lingr; size = sizeof(lingr); ret = getsockopt(fd, level, opt, &lingr, &size); if (!lingr.l_onoff) { value = -1; } else { value = lingr.l_linger; } break; } default: ret = getsockopt(fd, level, opt, &value, &size); break; } if (ret != 0) { jniThrowIOException(env, errno); return 0; } return value; }
//TODO change this to return an instance of LocalSocketAddress static jobject socket_getSockName(JNIEnv *env, jobject object, jobject fileDescriptor) { int err; int fd; if (fileDescriptor == NULL) { jniThrowNullPointerException(env, NULL); return NULL; } fd = jniGetFDFromFileDescriptor(env, fileDescriptor); if (env->ExceptionOccurred() != NULL) { return NULL; } union { struct sockaddr address; struct sockaddr_un un_address; } sa; memset(&sa, 0, sizeof(sa)); socklen_t namelen = sizeof(sa); err = getsockname(fd, &(sa.address), &namelen); if (err < 0) { jniThrowIOException(env, errno); return NULL; } if (sa.address.sa_family != AF_UNIX) { // We think we're an impl only for AF_UNIX, so this should never happen. jniThrowIOException(env, EINVAL); return NULL; } if (sa.un_address.sun_path[0] == '\0') { } else { } }
static jlong harmony_io_writeDirect(JNIEnv* env, jobject, jint fd, jint buf, jint offset, jint nbytes) { jbyte* src = reinterpret_cast<jbyte*>(buf + offset); jlong rc = TEMP_FAILURE_RETRY(write(fd, src, nbytes)); if (rc == -1) { jniThrowIOException(env, errno); } return rc; }
static void initSocketFromFdNative(JNIEnv *env, jobject obj, jint fd) { #ifdef HAVE_BLUETOOTH ALOGV("%s", __FUNCTION__); struct asocket *s = asocket_init(fd); if (!s) { ALOGV("asocket_init() failed, throwing"); jniThrowIOException(env, errno); return; } env->SetIntField(obj, field_mSocketData, (jint)s); return; #endif jniThrowIOException(env, ENOSYS); }
static jint Console_setEchoImpl(JNIEnv* env, jclass, jboolean on, jint previousState) { termios state; if (TEMP_FAILURE_RETRY(tcgetattr(STDIN_FILENO, &state)) == -1) { jniThrowIOException(env, errno); return 0; } if (on) { state.c_lflag = previousState; } else { previousState = state.c_lflag; state.c_lflag &= ~(ECHO | ECHOE | ECHOK | ECHONL); } if (TEMP_FAILURE_RETRY(tcsetattr(STDIN_FILENO, TCSAFLUSH, &state)) == -1) { jniThrowIOException(env, errno); return 0; } return previousState; }
static jint readNative(JNIEnv *env, jobject obj, jbyteArray jb, jint offset, jint length) { #ifdef HAVE_BLUETOOTH ALOGV("%s", __FUNCTION__); int ret; jbyte *b; int sz; struct asocket *s = get_socketData(env, obj); if (!s) return -1; if (jb == NULL) { jniThrowIOException(env, EINVAL); return -1; } sz = env->GetArrayLength(jb); if (offset < 0 || length < 0 || offset + length > sz) { jniThrowIOException(env, EINVAL); return -1; } b = env->GetByteArrayElements(jb, NULL); if (b == NULL) { jniThrowIOException(env, EINVAL); return -1; } ret = asocket_read(s, &b[offset], length, -1); if (ret < 0) { jniThrowIOException(env, errno); env->ReleaseByteArrayElements(jb, b, JNI_ABORT); return -1; } env->ReleaseByteArrayElements(jb, b, 0); return (jint)ret; #endif jniThrowIOException(env, ENOSYS); return -1; }
static jint harmony_io_truncate(JNIEnv* env, jobject, jint fd, jlong length) { if (offsetTooLarge(env, length)) { return -1; } int rc = ftruncate(fd, length); if (rc == -1) { jniThrowIOException(env, errno); } return rc; }
static void android_os_Power_reboot(JNIEnv *env, jobject clazz, jstring reason) { if (reason == NULL) { android_reboot(ANDROID_RB_RESTART, 0, 0); } else { const char *chars = env->GetStringUTFChars(reason, NULL); android_reboot(ANDROID_RB_RESTART2, 0, (char *) chars); env->ReleaseStringUTFChars(reason, chars); // In case it fails. } jniThrowIOException(env, errno); }
//JNI Method Called to respond to PDU 0x16 static jboolean sendValueTextRspNative(JNIEnv *env, jobject object, jint num_attr, jbyteArray attr, jint length , jobjectArray textArray ) { btrc_player_setting_text_t *pAttrs = NULL; bt_status_t status; int i; jstring text ; const char* textStr; jbyte *arr ; //ALOGE("sendValueTextRspNative"); if (!sBluetoothAvrcpInterface) return JNI_FALSE; if (num_attr > BTRC_MAX_ELEM_ATTR_SIZE) { ALOGE("sendValueTextRspNative: number of attributes exceed maximum"); return JNI_FALSE; } pAttrs = new btrc_player_setting_text_t[num_attr]; if (!pAttrs) { ALOGE("sendValueTextRspNative: not have enough memeory"); return JNI_FALSE; } arr = env->GetByteArrayElements(attr, NULL); if (!arr) { delete[] pAttrs; jniThrowIOException(env, EINVAL); return JNI_FALSE; } for (i = 0; i < num_attr ; ++i) { text = (jstring) env->GetObjectArrayElement(textArray, i); textStr = env->GetStringUTFChars(text, NULL); if (!textStr) { ALOGE("sendValueTextRspNative: GetStringUTFChars return NULL"); env->DeleteLocalRef(text); break; } pAttrs[i].id = arr[i]; if (strlen(textStr) >= BTRC_MAX_ATTR_STR_LEN) { ALOGE("sendValueTextRspNative: string length exceed maximum"); strncpy((char *)pAttrs[i].text, textStr, BTRC_MAX_ATTR_STR_LEN-1); pAttrs[i].text[BTRC_MAX_ATTR_STR_LEN-1] = 0; } else { strcpy((char *)pAttrs[i].text, textStr); } env->ReleaseStringUTFChars(text, textStr); env->DeleteLocalRef(text); } //Call Stack Method to Respond to PDU 0x16 if ((status = sBluetoothAvrcpInterface->get_player_app_value_text_rsp(num_attr, pAttrs)) != BT_STATUS_SUCCESS) { ALOGE("Failed get_player_app_value_text_rsp, status: %d", status); } delete[] pAttrs; env->ReleaseByteArrayElements(attr, arr, 0); return (status == BT_STATUS_SUCCESS) ? JNI_TRUE : JNI_FALSE; }
static jint availableNative(JNIEnv *env, jobject obj) { #ifdef HAVE_BLUETOOTH ALOGV("%s", __FUNCTION__); int available; struct asocket *s = get_socketData(env, obj); if (!s) return -1; if (ioctl(s->fd, FIONREAD, &available) < 0) { jniThrowIOException(env, errno); return -1; } return available; #endif jniThrowIOException(env, ENOSYS); return -1; }
static void setAmpPolicyNative(JNIEnv *env, jobject obj, jint amppol) { #ifdef HAVE_BLUETOOTH ALOGV(__FUNCTION__); struct asocket *s = get_socketData(env, obj); if (!s) return; int err; err = setsockopt(s->fd, SOL_BLUETOOTH, BT_AMP_POLICY, &pol, sizeof(amppol)); if (err) { ALOGV("setsockopt() failed, throwing"); jniThrowIOException(env, errno); return; } return; #endif jniThrowIOException(env, ENOSYS); }
/* * In class com.android.internal.os.ZygoteInit: * private static native int getpgid(int pid) */ static jint com_android_internal_os_ZygoteInit_getpgid( JNIEnv* env, jobject clazz, jint pid) { pid_t ret; ret = getpgid(pid); if (ret < 0) { jniThrowIOException(env, errno); } return ret; }
/** * Reads data from a socket into buf, processing any ancillary data * and adding it to thisJ. * * Returns the length of normal data read, or -1 if an exception has * been thrown in this function. */ static ssize_t socket_read_all(JNIEnv *env, jobject thisJ, int fd, void *buffer, size_t len) { ssize_t ret; ssize_t bytesread = 0; struct msghdr msg; struct iovec iv; unsigned char *buf = (unsigned char *)buffer; // Enough buffer for a pile of fd's. We throw an exception if // this buffer is too small. struct cmsghdr cmsgbuf[2*sizeof(cmsghdr) + 0x100]; memset(&msg, 0, sizeof(msg)); memset(&iv, 0, sizeof(iv)); iv.iov_base = buf; iv.iov_len = len; msg.msg_iov = &iv; msg.msg_iovlen = 1; msg.msg_control = cmsgbuf; msg.msg_controllen = sizeof(cmsgbuf); do { ret = recvmsg(fd, &msg, MSG_NOSIGNAL); } while (ret < 0 && errno == EINTR); if (ret < 0 && errno == EPIPE) { // Treat this as an end of stream return 0; } if (ret < 0) { jniThrowIOException(env, errno); return -1; } if ((msg.msg_flags & (MSG_CTRUNC | MSG_OOB | MSG_ERRQUEUE)) != 0) { // To us, any of the above flags are a fatal error jniThrowException(env, "java/io/IOException", "Unexpected error or truncation during recvmsg()"); return -1; } if (ret >= 0) { socket_process_cmsg(env, thisJ, &msg); } return ret; }
extern "C" jstring Java_java_io_File_realpath(JNIEnv* env, jclass, jstring javaPath) { ScopedUtfChars path(env, javaPath); if (path.c_str() == NULL) { return NULL; } std::string result; if (!realpath(path.c_str(), result)) { jniThrowIOException(env, errno); return NULL; } return env->NewStringUTF(result.c_str()); }
static jlong harmony_io_writev(JNIEnv* env, jobject, jint fd, jintArray jBuffers, jintArray jOffsets, jintArray jLengths, jint size) { iovec* vectors = initIoVec(env, jBuffers, jOffsets, jLengths, size); if (vectors == NULL) { return -1; } long result = writev(fd, vectors, size); if (result == -1) { jniThrowIOException(env, errno); } delete[] vectors; return result; }
static jint android_util_MemoryIntArray_size(JNIEnv* env, jobject clazz, jint fd) { if (fd < 0) { jniThrowException(env, "java/io/IOException", "bad file descriptor"); return -1; } int ashmemSize = ashmem_get_size_region(fd); if (ashmemSize < 0) { // Some other error, throw exception jniThrowIOException(env, errno); return -1; } return ashmemSize / sizeof(std::atomic_int); }
/* * private native FileDescriptor * create_native(boolean stream) * throws IOException; */ static jobject socket_create (JNIEnv *env, jobject object, jboolean stream) { int ret; ret = socket(PF_LOCAL, stream ? SOCK_STREAM : SOCK_DGRAM, 0); if (ret < 0) { jniThrowIOException(env, errno); return NULL; } return jniCreateFileDescriptor(env,ret); }
static jstring File_realpath(JNIEnv* env, jclass, jstring javaPath) { ScopedUtfChars path(env, javaPath); if (path.c_str() == NULL) { return NULL; } extern bool realpath(const char* path, std::string& resolved); std::string result; if (!realpath(path.c_str(), result)) { jniThrowIOException(env, errno); return NULL; } return env->NewStringUTF(result.c_str()); }
static void abortNative(JNIEnv *env, jobject obj) { #ifdef HAVE_BLUETOOTH ALOGV("%s", __FUNCTION__); struct asocket *s = get_socketData(env, obj); if (!s) return; asocket_abort(s); ALOGV("...asocket_abort(%d) complete", s->fd); return; #endif jniThrowIOException(env, ENOSYS); }
static int getConnectionStateNative(JNIEnv* env, jobject obj, jbyteArray address) { ALOGV("%s:",__FUNCTION__); if (!sBluetoothInterface) return JNI_FALSE; jbyte *addr = env->GetByteArrayElements(address, NULL); if (addr == NULL) { jniThrowIOException(env, EINVAL); return JNI_FALSE; } int ret = sBluetoothInterface->get_connection_state((bt_bdaddr_t *)addr); env->ReleaseByteArrayElements(address, addr, 0); return ret; }
static jboolean java_io_File_createNewFileImpl(JNIEnv* env, jobject, jbyteArray pathBytes) { ScopedByteArray path(env, pathBytes); // On Android, we don't want default permissions to allow global access. ScopedFd fd(open(&path[0], O_CREAT | O_EXCL, 0600)); if (fd.get() != -1) { // We created a new file. Success! return JNI_TRUE; } if (errno == EEXIST) { // The file already exists. return JNI_FALSE; } jniThrowIOException(env, errno); return JNI_FALSE; // Ignored by Java; keeps the C++ compiler happy. }
static jlong harmony_io_readDirect(JNIEnv* env, jobject, jint fd, jint buf, jint offset, jint nbytes) { if (nbytes == 0) { return 0; } jbyte* dst = reinterpret_cast<jbyte*>(buf + offset); jlong rc = TEMP_FAILURE_RETRY(read(fd, dst, nbytes)); if (rc == 0) { return -1; } if (rc == -1) { jniThrowIOException(env, errno); } return rc; }
static void destroyNative(JNIEnv *env, jobject obj) { #ifdef HAVE_BLUETOOTH LOGV(__FUNCTION__); struct asocket *s = get_socketData(env, obj); int fd = s->fd; if (!s) return; asocket_destroy(s); LOGV("...asocket_destroy(%d) complete", fd); return; #endif jniThrowIOException(env, ENOSYS); }