diff options
Diffstat (limited to 'core/jni/android_nio_utils.cpp')
-rw-r--r-- | core/jni/android_nio_utils.cpp | 114 |
1 files changed, 114 insertions, 0 deletions
diff --git a/core/jni/android_nio_utils.cpp b/core/jni/android_nio_utils.cpp new file mode 100644 index 0000000..584e7a4 --- /dev/null +++ b/core/jni/android_nio_utils.cpp @@ -0,0 +1,114 @@ +/* + * Copyright (C) 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. + * 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 "android_nio_utils.h" + +struct NioJNIData { + jclass nioAccessClass; + + jmethodID getBasePointerID; + jmethodID getBaseArrayID; + jmethodID getBaseArrayOffsetID; +}; + +static NioJNIData gNioJNI; + +void* android::nio_getPointer(JNIEnv *_env, jobject buffer, jarray *array) { + assert(array); + + jlong pointer; + jint offset; + void *data; + + pointer = _env->CallStaticLongMethod(gNioJNI.nioAccessClass, + gNioJNI.getBasePointerID, buffer); + if (pointer != 0L) { + *array = NULL; + return (void *) (jint) pointer; + } + + *array = (jarray) _env->CallStaticObjectMethod(gNioJNI.nioAccessClass, + gNioJNI.getBaseArrayID, buffer); + offset = _env->CallStaticIntMethod(gNioJNI.nioAccessClass, + gNioJNI.getBaseArrayOffsetID, buffer); + data = _env->GetPrimitiveArrayCritical(*array, (jboolean *) 0); + + return (void *) ((char *) data + offset); +} + + +void android::nio_releasePointer(JNIEnv *_env, jarray array, void *data, + jboolean commit) { + _env->ReleasePrimitiveArrayCritical(array, data, + commit ? 0 : JNI_ABORT); +} + +/////////////////////////////////////////////////////////////////////////////// + +android::AutoBufferPointer::AutoBufferPointer(JNIEnv* env, jobject nioBuffer, + jboolean commit) { + fEnv = env; + fCommit = commit; + fPointer = android::nio_getPointer(env, nioBuffer, &fArray); +} + +android::AutoBufferPointer::~AutoBufferPointer() { + if (NULL != fArray) { + android::nio_releasePointer(fEnv, fArray, fPointer, fCommit); + } +} + +/////////////////////////////////////////////////////////////////////////////// + +static jclass findClass(JNIEnv* env, const char name[]) { + jclass c = env->FindClass(name); + LOG_FATAL_IF(!c, "Unable to find class %s", name); + return c; +} + +static jmethodID findStaticMethod(JNIEnv* env, jclass c, const char method[], + const char params[]) { + jmethodID m = env->GetStaticMethodID(c, method, params); + LOG_FATAL_IF(!m, "Unable to find method %s", method); + return m; +} + +static jfieldID getFieldID(JNIEnv* env, jclass c, const char name[], + const char type[]) { + jfieldID f = env->GetFieldID(c, name, type); + LOG_FATAL_IF(!f, "Unable to find field %s", name); + return f; +} + +namespace android { + +int register_android_nio_utils(JNIEnv* env); +int register_android_nio_utils(JNIEnv* env) { + jclass localClass = findClass(env, "java/nio/NIOAccess"); + gNioJNI.getBasePointerID = findStaticMethod(env, localClass, + "getBasePointer", "(Ljava/nio/Buffer;)J"); + gNioJNI.getBaseArrayID = findStaticMethod(env, localClass, + "getBaseArray", "(Ljava/nio/Buffer;)Ljava/lang/Object;"); + gNioJNI.getBaseArrayOffsetID = findStaticMethod(env, localClass, + "getBaseArrayOffset", "(Ljava/nio/Buffer;)I"); + + // now record a permanent version of the class ID + gNioJNI.nioAccessClass = (jclass) env->NewGlobalRef(localClass); + + return 0; +} + +} |