diff options
author | Orion Hodson <oth@google.com> | 2019-02-22 16:41:10 +0000 |
---|---|---|
committer | Orion Hodson <oth@google.com> | 2019-04-11 16:53:46 +0100 |
commit | bcc2b6fda49e42add4715882231215b2b3ada9d0 (patch) | |
tree | 9345e8f3e6e5eef59d8ec9ccc29cafda6a8c5a4d | |
parent | 99b0113fdcb2abb2c0f7043d21b9ccfaae8c78d1 (diff) | |
download | libnativehelper-android-10.0.0_r22.tar.gz |
Add java.nio.Buffer helper methods.android-mainline-10.0.0_r9android-mainline-10.0.0_r7android-mainline-10.0.0_r5android-mainline-10.0.0_r4android-mainline-10.0.0_r10android-10.0.0_r9android-10.0.0_r8android-10.0.0_r7android-10.0.0_r45android-10.0.0_r44android-10.0.0_r43android-10.0.0_r42android-10.0.0_r41android-10.0.0_r40android-10.0.0_r39android-10.0.0_r38android-10.0.0_r37android-10.0.0_r36android-10.0.0_r35android-10.0.0_r34android-10.0.0_r33android-10.0.0_r32android-10.0.0_r31android-10.0.0_r30android-10.0.0_r29android-10.0.0_r28android-10.0.0_r27android-10.0.0_r26android-10.0.0_r25android-10.0.0_r24android-10.0.0_r23android-10.0.0_r22android-10.0.0_r21android-10.0.0_r20android-10.0.0_r19android-10.0.0_r18android-10.0.0_r16android-10.0.0_r15android-10.0.0_r14android-10.0.0_r13android-10.0.0_r12android10-qpr3-s1-releaseandroid10-qpr3-releaseandroid10-qpr2-s4-releaseandroid10-qpr2-s3-releaseandroid10-qpr2-s2-releaseandroid10-qpr2-s1-releaseandroid10-qpr2-releaseandroid10-qpr1-releaseandroid10-qpr1-mainline-releaseandroid10-qpr1-d-releaseandroid10-qpr1-c-s1-releaseandroid10-qpr1-c-releaseandroid10-qpr1-b-s1-releaseandroid10-qpr1-b-releaseandroid10-mainline-media-releaseandroid10-devandroid10-d4-s1-releaseandroid10-d4-releaseandroid10-c2f2-s2-releaseandroid10-c2f2-s1-releaseandroid10-c2f2-release
Bug: 124338141
Test: Boot and observe no core platform api warnings from opengl
(cherry picked from commit f5480bdcdd27e492a9858599664c74e16a46a961)
Change-Id: I4680418398f0708c26c0124b418a2ccb1094a038
Merged-In: I6db85f6084dd620e08568dbdeea0d10efb20a84f
-rw-r--r-- | JNIHelp.cpp | 37 | ||||
-rw-r--r-- | JniConstants.cpp | 113 | ||||
-rw-r--r-- | JniConstants.h | 30 | ||||
-rw-r--r-- | include/nativehelper/JNIHelp.h | 60 | ||||
-rw-r--r-- | libnativehelper.map.txt | 4 |
5 files changed, 240 insertions, 4 deletions
diff --git a/JNIHelp.cpp b/JNIHelp.cpp index 867488b..8432f7a 100644 --- a/JNIHelp.cpp +++ b/JNIHelp.cpp @@ -355,6 +355,43 @@ MODULE_API jlong jniGetOwnerIdFromFileDescriptor(C_JNIEnv* env, jobject fileDesc return e->GetLongField(fileDescriptor, JniConstants::GetFileDescriptorOwnerIdField(e)); } +MODULE_API jarray jniGetNioBufferBaseArray(C_JNIEnv* env, jobject nioBuffer) { + JNIEnv* e = reinterpret_cast<JNIEnv*>(env); + jclass nioAccessClass = JniConstants::GetNioAccessClass(e); + jmethodID getBaseArrayMethod = JniConstants::GetNioAccessGetBaseArrayMethod(e); + jobject object = e->CallStaticObjectMethod(nioAccessClass, getBaseArrayMethod, nioBuffer); + return static_cast<jarray>(object); +} + +MODULE_API int jniGetNioBufferBaseArrayOffset(C_JNIEnv* env, jobject nioBuffer) { + JNIEnv* e = reinterpret_cast<JNIEnv*>(env); + jclass nioAccessClass = JniConstants::GetNioAccessClass(e); + jmethodID getBaseArrayOffsetMethod = JniConstants::GetNioAccessGetBaseArrayOffsetMethod(e); + return e->CallStaticIntMethod(nioAccessClass, getBaseArrayOffsetMethod, nioBuffer); +} + +MODULE_API jlong jniGetNioBufferPointer(C_JNIEnv* env, jobject nioBuffer) { + JNIEnv* e = reinterpret_cast<JNIEnv*>(env); + jlong baseAddress = e->GetLongField(nioBuffer, JniConstants::GetNioBufferAddressField(e)); + if (baseAddress != 0) { + const int position = e->GetIntField(nioBuffer, JniConstants::GetNioBufferPositionField(e)); + const int shift = + e->GetIntField(nioBuffer, JniConstants::GetNioBufferElementSizeShiftField(e)); + baseAddress += position << shift; + } + return baseAddress; +} + +MODULE_API jlong jniGetNioBufferFields(C_JNIEnv* env, jobject nioBuffer, + jint* position, jint* limit, jint* elementSizeShift) { + JNIEnv* e = reinterpret_cast<JNIEnv*>(env); + *position = e->GetIntField(nioBuffer, JniConstants::GetNioBufferPositionField(e)); + *limit = e->GetIntField(nioBuffer, JniConstants::GetNioBufferLimitField(e)); + *elementSizeShift = + e->GetIntField(nioBuffer, JniConstants::GetNioBufferElementSizeShiftField(e)); + return e->GetLongField(nioBuffer, JniConstants::GetNioBufferAddressField(e)); +} + MODULE_API jobject jniGetReferent(C_JNIEnv* env, jobject ref) { JNIEnv* e = reinterpret_cast<JNIEnv*>(env); return e->CallObjectMethod(ref, JniConstants::GetReferenceGetMethod(e)); diff --git a/JniConstants.cpp b/JniConstants.cpp index 3a0de9d..6d6ce79 100644 --- a/JniConstants.cpp +++ b/JniConstants.cpp @@ -42,6 +42,8 @@ std::atomic<bool> g_class_refs_initialized(false); // retrieve one of these classes. jclass g_file_descriptor_class = nullptr; // java.io.FileDescriptor +jclass g_nio_access_class = nullptr; // java.nio.Access +jclass g_nio_buffer_class = nullptr; // java.nio.Buffer jclass g_reference_class = nullptr; // java.lang.ref.Reference jclass g_string_class = nullptr; // java.lang.String @@ -70,6 +72,14 @@ jclass g_string_class = nullptr; // java.lang.String jfieldID g_file_descriptor_descriptor_field = nullptr; // java.io.FileDescriptor.descriptor jfieldID g_file_descriptor_owner_id_field = nullptr; // java.io.FileDescriptor.ownerId jmethodID g_file_descriptor_init_method = nullptr; // void java.io.FileDescriptor.<init>() +jmethodID g_nio_access_get_base_array_method = nullptr; // Object java.nio.NIOAccess.getBaseArray() +jmethodID g_nio_access_get_base_array_offset_method = nullptr; // Object java.nio.NIOAccess.getBaseArray() +jfieldID g_nio_buffer_address_field = nullptr; // long java.nio.Buffer.address +jfieldID g_nio_buffer_element_size_shift_field = nullptr; // int java.nio.Buffer._elementSizeShift +jfieldID g_nio_buffer_limit_field = nullptr; // int java.nio.Buffer.limit +jfieldID g_nio_buffer_position_field = nullptr; // int java.nio.Buffer.position +jmethodID g_nio_buffer_array_method = nullptr; // Object java.nio.Buffer.array() +jmethodID g_nio_buffer_array_offset_method = nullptr; // int java.nio.Buffer.arrayOffset() jmethodID g_reference_get_method = nullptr; // Object java.lang.ref.Reference.get() jclass FindClass(JNIEnv* env, const char* name) { @@ -90,16 +100,32 @@ jmethodID FindMethod(JNIEnv* env, jclass klass, const char* name, const char* si return result; } +jmethodID FindStaticMethod(JNIEnv* env, jclass klass, const char* name, const char* signature) { + jmethodID result = env->GetStaticMethodID(klass, name, signature); + ALOG_ALWAYS_FATAL_IF(result == nullptr, "failed to find static method '%s%s'", name, signature); + return result; +} + } // namespace -jclass JniConstants::GetReferenceClass(JNIEnv* env) { +jclass JniConstants::GetFileDescriptorClass(JNIEnv* env) { EnsureClassReferencesInitialized(env); - return g_reference_class; + return g_file_descriptor_class; } -jclass JniConstants::GetFileDescriptorClass(JNIEnv* env) { +jclass JniConstants::GetNioAccessClass(JNIEnv* env) { EnsureClassReferencesInitialized(env); - return g_file_descriptor_class; + return g_nio_access_class; +} + +jclass JniConstants::GetNioBufferClass(JNIEnv* env) { + EnsureClassReferencesInitialized(env); + return g_nio_buffer_class; +} + +jclass JniConstants::GetReferenceClass(JNIEnv* env) { + EnsureClassReferencesInitialized(env); + return g_reference_class; } jclass JniConstants::GetStringClass(JNIEnv* env) { @@ -131,6 +157,73 @@ jmethodID JniConstants::GetFileDescriptorInitMethod(JNIEnv* env) { return g_file_descriptor_init_method; } +jmethodID JniConstants::GetNioAccessGetBaseArrayMethod(JNIEnv* env) { + if (g_nio_access_get_base_array_method == nullptr) { + jclass klass = GetNioAccessClass(env); + g_nio_access_get_base_array_method = + FindStaticMethod(env, klass, "getBaseArray", + "(Ljava/nio/Buffer;)Ljava/lang/Object;"); + } + return g_nio_access_get_base_array_method; +} + +jmethodID JniConstants::GetNioAccessGetBaseArrayOffsetMethod(JNIEnv* env) { + if (g_nio_access_get_base_array_offset_method == nullptr) { + jclass klass = GetNioAccessClass(env); + g_nio_access_get_base_array_offset_method = + FindStaticMethod(env, klass, "getBaseArrayOffset", "(Ljava/nio/Buffer;)I"); + } + return g_nio_access_get_base_array_offset_method; +} + +jfieldID JniConstants::GetNioBufferAddressField(JNIEnv* env) { + if (g_nio_buffer_address_field == nullptr) { + jclass klass = GetNioBufferClass(env); + g_nio_buffer_address_field = FindField(env, klass, "address", "J"); + } + return g_nio_buffer_address_field; +} + +jfieldID JniConstants::GetNioBufferElementSizeShiftField(JNIEnv* env) { + if (g_nio_buffer_element_size_shift_field == nullptr) { + jclass klass = GetNioBufferClass(env); + g_nio_buffer_element_size_shift_field = FindField(env, klass, "_elementSizeShift", "I"); + } + return g_nio_buffer_element_size_shift_field; +} + +jfieldID JniConstants::GetNioBufferLimitField(JNIEnv* env) { + if (g_nio_buffer_limit_field == nullptr) { + jclass klass = GetNioBufferClass(env); + g_nio_buffer_limit_field = FindField(env, klass, "limit", "I"); + } + return g_nio_buffer_limit_field; +} + +jfieldID JniConstants::GetNioBufferPositionField(JNIEnv* env) { + if (g_nio_buffer_position_field == nullptr) { + jclass klass = GetNioBufferClass(env); + g_nio_buffer_position_field = FindField(env, klass, "position", "I"); + } + return g_nio_buffer_position_field; +} + +jmethodID JniConstants::GetNioBufferArrayMethod(JNIEnv* env) { + if (g_nio_buffer_array_method == nullptr) { + jclass klass = GetNioBufferClass(env); + g_nio_buffer_array_method = FindMethod(env, klass, "array", "()Ljava/lang/Object;"); + } + return g_nio_buffer_array_method; +} + +jmethodID JniConstants::GetNioBufferArrayOffsetMethod(JNIEnv* env) { + if (g_nio_buffer_array_offset_method == nullptr) { + jclass klass = GetNioBufferClass(env); + g_nio_buffer_array_offset_method = FindMethod(env, klass, "arrayOffset", "()I"); + } + return g_nio_buffer_array_offset_method; +} + jmethodID JniConstants::GetReferenceGetMethod(JNIEnv* env) { if (g_reference_get_method == nullptr) { jclass klass = GetReferenceClass(env); @@ -156,6 +249,8 @@ void JniConstants::EnsureClassReferencesInitialized(JNIEnv* env) { // are not references and races only have trivial performance // consequences. g_file_descriptor_class = FindClass(env, "java/io/FileDescriptor"); + g_nio_access_class = FindClass(env, "java/nio/NIOAccess"); + g_nio_buffer_class = FindClass(env, "java/nio/Buffer"); g_reference_class = FindClass(env, "java/lang/ref/Reference"); g_string_class = FindClass(env, "java/lang/String"); g_class_refs_initialized.store(true, std::memory_order_release); @@ -175,6 +270,16 @@ void JniConstants::Uninitialize() { g_file_descriptor_descriptor_field = nullptr; g_file_descriptor_owner_id_field = nullptr; g_file_descriptor_init_method = nullptr; + g_nio_access_class = nullptr; + g_nio_access_get_base_array_method = nullptr; + g_nio_access_get_base_array_offset_method = nullptr; + g_nio_buffer_class = nullptr; + g_nio_buffer_address_field = nullptr; + g_nio_buffer_element_size_shift_field = nullptr; + g_nio_buffer_limit_field = nullptr; + g_nio_buffer_position_field = nullptr; + g_nio_buffer_array_method = nullptr; + g_nio_buffer_array_offset_method = nullptr; g_reference_class = nullptr; g_reference_get_method = nullptr; g_string_class = nullptr; diff --git a/JniConstants.h b/JniConstants.h index 617cf43..b2d03be 100644 --- a/JniConstants.h +++ b/JniConstants.h @@ -31,6 +31,36 @@ struct JniConstants { // void java.io.FileDescriptor.<init>(). static jmethodID GetFileDescriptorInitMethod(JNIEnv* env); + // Global reference to java.nio.NIOAccess. + static jclass GetNioAccessClass(JNIEnv* env); + + // Object java.nio.NIOAccess.getBaseArray(Buffer); + static jmethodID GetNioAccessGetBaseArrayMethod(JNIEnv* env); + + // int java.nio.NIOAccess.getBaseArrayOffset(Buffer); + static jmethodID GetNioAccessGetBaseArrayOffsetMethod(JNIEnv* env); + + // Global reference to java.nio.Buffer. + static jclass GetNioBufferClass(JNIEnv* env); + + // long java.nio.Buffer.address + static jfieldID GetNioBufferAddressField(JNIEnv* env); + + // int java.nio.Buffer._elementSizeShift + static jfieldID GetNioBufferElementSizeShiftField(JNIEnv* env); + + // int java.nio.Buffer.limit; + static jfieldID GetNioBufferLimitField(JNIEnv* env); + + // int java.nio.Buffer.position; + static jfieldID GetNioBufferPositionField(JNIEnv* env); + + // Object java.nio.Buffer.array() + static jmethodID GetNioBufferArrayMethod(JNIEnv* env); + + // int java.nio.Buffer.arrayOffset() + static jmethodID GetNioBufferArrayOffsetMethod(JNIEnv* env); + // Global reference to java.lang.ref.Reference. static jclass GetReferenceClass(JNIEnv* env); diff --git a/include/nativehelper/JNIHelp.h b/include/nativehelper/JNIHelp.h index 3076678..bab5dd5 100644 --- a/include/nativehelper/JNIHelp.h +++ b/include/nativehelper/JNIHelp.h @@ -122,6 +122,48 @@ MODULE_API void jniSetFileDescriptorOfFD(C_JNIEnv* env, MODULE_API jlong jniGetOwnerIdFromFileDescriptor(C_JNIEnv* env, jobject fileDescriptor); /* + * Gets the managed heap array backing a java.nio.Buffer instance. + * + * Returns nullptr if there is no array backing. + * + * This method performs a JNI call to java.nio.NIOAccess.getBaseArray(). + */ +MODULE_API jarray jniGetNioBufferBaseArray(C_JNIEnv* env, jobject nioBuffer); + +/* + * Gets the offset in bytes from the start of the managed heap array backing the buffer. + * + * Returns 0 if there is no array backing. + * + * This method performs a JNI call to java.nio.NIOAccess.getBaseArrayOffset(). + */ +MODULE_API jint jniGetNioBufferBaseArrayOffset(C_JNIEnv* env, jobject nioBuffer); + +/* + * Gets field information from a java.nio.Buffer instance. + * + * Reads the |position|, |limit|, and |elementSizeShift| fields from the buffer instance. + * + * Returns the |address| field of the java.nio.Buffer instance which is only valid (non-zero) when + * the buffer is backed by a direct buffer. + */ +MODULE_API jlong jniGetNioBufferFields(C_JNIEnv* env, + jobject nioBuffer, + /*out*/jint* position, + /*out*/jint* limit, + /*out*/jint* elementSizeShift); + +/* + * Gets the current position from a java.nio.Buffer as a pointer to memory in a fixed buffer. + * + * Returns 0 if |nioBuffer| is not backed by a direct buffer. + * + * This method reads the |address|, |position|, and |elementSizeShift| fields from the + * java.nio.Buffer instance to calculate the pointer address for the current position. + */ +MODULE_API jlong jniGetNioBufferPointer(C_JNIEnv* env, jobject nioBuffer); + +/* * Returns the reference from a java.lang.ref.Reference. */ MODULE_API jobject jniGetReferent(C_JNIEnv* env, jobject ref); @@ -196,6 +238,24 @@ inline jlong jniGetOwnerIdFromFileDescriptor(JNIEnv* env, jobject fileDescriptor return jniGetOwnerIdFromFileDescriptor(&env->functions, fileDescriptor); } +inline jarray jniGetNioBufferBaseArray(JNIEnv* env, jobject nioBuffer) { + return jniGetNioBufferBaseArray(&env->functions, nioBuffer); +} + +inline jint jniGetNioBufferBaseArrayOffset(JNIEnv* env, jobject nioBuffer) { + return jniGetNioBufferBaseArrayOffset(&env->functions, nioBuffer); +} + +inline jlong jniGetNioBufferFields(JNIEnv* env, jobject nioBuffer, + jint* position, jint* limit, jint* elementSizeShift) { + return jniGetNioBufferFields(&env->functions, nioBuffer, + position, limit, elementSizeShift); +} + +inline jlong jniGetNioBufferPointer(JNIEnv* env, jobject nioBuffer) { + return jniGetNioBufferPointer(&env->functions, nioBuffer); +} + inline jobject jniGetReferent(JNIEnv* env, jobject ref) { return jniGetReferent(&env->functions, ref); } diff --git a/libnativehelper.map.txt b/libnativehelper.map.txt index 81579a5..62c980d 100644 --- a/libnativehelper.map.txt +++ b/libnativehelper.map.txt @@ -18,6 +18,10 @@ LIBNATIVEHELPER_1 { jniGetFDFromFileDescriptor; jniSetFileDescriptorOfFD; jniGetOwnerIdFromFileDescriptor; + jniGetNioBufferBaseArray; + jniGetNioBufferBaseArrayOffset; + jniGetNioBufferPointer; + jniGetNioBufferFields; jniGetReferent; jniCreateString; jniLogException; |