summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
author Tom Mulcahy <tomm@squareup.com> 2024-04-30 22:55:29 +0000
committer Cherrypicker Worker <android-build-cherrypicker-worker@google.com> 2024-04-30 22:55:29 +0000
commit00867227b1ed1b3cc59fd344b83feeea524b42c9 (patch)
tree8a41d615cec379f5df1cd18c4149375ac4741e30
parenta7cbd3c84aa6a1b5fb81b821ae349e2dc1596f5f (diff)
usb: Use Get/SetByteArrayRegion in bulkTransfer
This change fixes https://issuetracker.google.com/issues/335003907 This change replaces GetPrimitiveArrayCritical/ReleasePrimitiveArrayCritical with GetByteArrayRegion/SetByteArrayRegion. This change is needed because the critical API variants are not appropriate for this context. See the JNI docs: After calling GetPrimitiveArrayCritical, the native code should not run for an extended period of time before it calls ReleasePrimitiveArrayCritical. In bulkTransfer, we call usb_device_bulk_transfer between GetPrimitiveArrayCritical/ReleasePrimitiveArrayCritical. usb_device_bulk_transfer is a blocking call so this can lead to GC hangs. Instead, we allocate a new buffer with malloc and then call GetByteArrayRegion/SetByteArrayRegion before/after usb_device_bulk_transfer, depending on the direction of the endpoint. Test: I ran UsbTests. I also sent a "TEST UNIT READY" to a USB drive and verified the response. (cherry picked from https://android-review.googlesource.com/q/commit:59548b0121d4492e4b55eceafa150b6af1a41a76) Merged-In: I5c82aac3fe99e1f11044f20091bf3a940bc8f6a7 Change-Id: I5c82aac3fe99e1f11044f20091bf3a940bc8f6a7
-rw-r--r--core/jni/android_hardware_UsbDeviceConnection.cpp16
1 files changed, 10 insertions, 6 deletions
diff --git a/core/jni/android_hardware_UsbDeviceConnection.cpp b/core/jni/android_hardware_UsbDeviceConnection.cpp
index a0228428e90e..7267eb8cb3dc 100644
--- a/core/jni/android_hardware_UsbDeviceConnection.cpp
+++ b/core/jni/android_hardware_UsbDeviceConnection.cpp
@@ -190,17 +190,21 @@ android_hardware_UsbDeviceConnection_bulk_request(JNIEnv *env, jobject thiz,
return -1;
}
- jbyte* bufferBytes = NULL;
- if (buffer) {
- bufferBytes = (jbyte*)env->GetPrimitiveArrayCritical(buffer, NULL);
+ bool is_dir_in = (endpoint & USB_ENDPOINT_DIR_MASK) == USB_DIR_IN;
+ jbyte *bufferBytes = (jbyte *)malloc(length);
+
+ if (!is_dir_in && buffer) {
+ env->GetByteArrayRegion(buffer, start, length, bufferBytes);
}
- jint result = usb_device_bulk_transfer(device, endpoint, bufferBytes + start, length, timeout);
+ jint result = usb_device_bulk_transfer(device, endpoint, bufferBytes, length, timeout);
- if (bufferBytes) {
- env->ReleasePrimitiveArrayCritical(buffer, bufferBytes, 0);
+ if (is_dir_in && buffer) {
+ env->SetByteArrayRegion(buffer, start, length, bufferBytes);
}
+ free(bufferBytes);
+
return result;
}