OSDN Git Service

Remove urb request size maximum for P api
authorJerry Zhang <zhangjerry@google.com>
Thu, 8 Feb 2018 00:14:25 +0000 (16:14 -0800)
committerJerry Zhang <zhangjerry@google.com>
Fri, 16 Feb 2018 01:09:42 +0000 (01:09 +0000)
The 16kB maximum for transfers was removed from
the kernel in 3.3. Devio has since supported
arbitrary transfer sizes through scatter gather.

See the following kernel patches for context:
"USB: change the memory limits in usbfs URB submission"
"usbdevfs: Use scatter-gather lists for large bulk transfers".

Larger buffer sizes will be allowed for apps targeting
P and greater. For apps targeting previous apis, the
previous behavior of truncating length to 16384 will
be applied here instead of libusbhost, for bulk transfers
and queue(ByteBuffer, int). The previous behavior
of throwing an exception will continue to apply
for queue(ByteBuffer).

Bug: 67683483
Test: Run usb_async_test app with USB3 : 38MB/s -> 300MB/s
Test: CtsVerifier UsbDeviceTests pass
Change-Id: Ia52440cb725561b0f1db1a75aa1b8ab952585826

core/java/android/hardware/usb/UsbDeviceConnection.java
core/java/android/hardware/usb/UsbRequest.java

index 5b15c0d..9e5174a 100644 (file)
@@ -222,7 +222,10 @@ public class UsbDeviceConnection {
      * @param endpoint the endpoint for this transaction
      * @param buffer buffer for data to send or receive; can be {@code null} to wait for next
      *               transaction without reading data
-     * @param length the length of the data to send or receive
+     * @param length the length of the data to send or receive. Before
+     *               {@value Build.VERSION_CODES#P}, a value larger than 16384 bytes
+     *               would be truncated down to 16384. In API {@value Build.VERSION_CODES#P}
+     *               and after, any value of length is valid.
      * @param timeout in milliseconds, 0 is infinite
      * @return length of data transferred (or zero) for success,
      * or negative value for failure
@@ -239,7 +242,10 @@ public class UsbDeviceConnection {
      * @param endpoint the endpoint for this transaction
      * @param buffer buffer for data to send or receive
      * @param offset the index of the first byte in the buffer to send or receive
-     * @param length the length of the data to send or receive
+     * @param length the length of the data to send or receive. Before
+     *               {@value Build.VERSION_CODES#P}, a value larger than 16384 bytes
+     *               would be truncated down to 16384. In API {@value Build.VERSION_CODES#P}
+     *               and after, any value of length is valid.
      * @param timeout in milliseconds, 0 is infinite
      * @return length of data transferred (or zero) for success,
      * or negative value for failure
@@ -247,6 +253,10 @@ public class UsbDeviceConnection {
     public int bulkTransfer(UsbEndpoint endpoint,
             byte[] buffer, int offset, int length, int timeout) {
         checkBounds(buffer, offset, length);
+        if (mContext.getApplicationInfo().targetSdkVersion < Build.VERSION_CODES.P
+                && length > UsbRequest.MAX_USBFS_BUFFER_SIZE) {
+            length = UsbRequest.MAX_USBFS_BUFFER_SIZE;
+        }
         return native_bulk_request(endpoint.getAddress(), buffer, offset, length, timeout);
     }
 
index 2e8f8e1..f59c87e 100644 (file)
@@ -17,6 +17,7 @@
 package android.hardware.usb;
 
 import android.annotation.Nullable;
+import android.os.Build;
 import android.util.Log;
 
 import com.android.internal.util.Preconditions;
@@ -43,7 +44,7 @@ public class UsbRequest {
     private static final String TAG = "UsbRequest";
 
     // From drivers/usb/core/devio.c
-    private static final int MAX_USBFS_BUFFER_SIZE = 16384;
+    static final int MAX_USBFS_BUFFER_SIZE = 16384;
 
     // used by the JNI code
     private long mNativeContext;
@@ -175,7 +176,9 @@ public class UsbRequest {
      *               capacity will be ignored. Once the request
      *               {@link UsbDeviceConnection#requestWait() is processed} the position will be set
      *               to the number of bytes read/written.
-     * @param length number of bytes to read or write.
+     * @param length number of bytes to read or write. Before {@value Build.VERSION_CODES#P}, a
+     *               value larger than 16384 bytes would be truncated down to 16384. In API
+     *               {@value Build.VERSION_CODES#P} and after, any value of length is valid.
      *
      * @return true if the queueing operation succeeded
      *
@@ -186,6 +189,11 @@ public class UsbRequest {
         boolean out = (mEndpoint.getDirection() == UsbConstants.USB_DIR_OUT);
         boolean result;
 
+        if (mConnection.getContext().getApplicationInfo().targetSdkVersion < Build.VERSION_CODES.P
+                && length > MAX_USBFS_BUFFER_SIZE) {
+            length = MAX_USBFS_BUFFER_SIZE;
+        }
+
         synchronized (mLock) {
             // save our buffer for when the request has completed
             mBuffer = buffer;
@@ -222,7 +230,10 @@ public class UsbRequest {
      *               of the buffer is undefined until the request is returned by
      *               {@link UsbDeviceConnection#requestWait}. If the request failed the buffer
      *               will be unchanged; if the request succeeded the position of the buffer is
-     *               incremented by the number of bytes sent/received.
+     *               incremented by the number of bytes sent/received. Before
+     *               {@value Build.VERSION_CODES#P}, a buffer of length larger than 16384 bytes
+     *               would throw IllegalArgumentException. In API {@value Build.VERSION_CODES#P}
+     *               and after, any size buffer is valid.
      *
      * @return true if the queueing operation succeeded
      */
@@ -244,9 +255,12 @@ public class UsbRequest {
                 mIsUsingNewQueue = true;
                 wasQueued = native_queue(null, 0, 0);
             } else {
-                // Can only send/receive MAX_USBFS_BUFFER_SIZE bytes at once
-                Preconditions.checkArgumentInRange(buffer.remaining(), 0, MAX_USBFS_BUFFER_SIZE,
-                        "number of remaining bytes");
+                if (mConnection.getContext().getApplicationInfo().targetSdkVersion
+                        < Build.VERSION_CODES.P) {
+                    // Can only send/receive MAX_USBFS_BUFFER_SIZE bytes at once
+                    Preconditions.checkArgumentInRange(buffer.remaining(), 0, MAX_USBFS_BUFFER_SIZE,
+                            "number of remaining bytes");
+                }
 
                 // Can not receive into read-only buffers.
                 Preconditions.checkArgument(!(buffer.isReadOnly() && !isSend), "buffer can not be "