Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit 910e9b04 authored by Jerry Zhang's avatar Jerry Zhang
Browse files

Remove urb request size maximum for P api

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
parent 1eb43b98
Loading
Loading
Loading
Loading
+12 −2
Original line number Original line Diff line number Diff line
@@ -222,7 +222,10 @@ public class UsbDeviceConnection {
     * @param endpoint the endpoint for this transaction
     * @param endpoint the endpoint for this transaction
     * @param buffer buffer for data to send or receive; can be {@code null} to wait for next
     * @param buffer buffer for data to send or receive; can be {@code null} to wait for next
     *               transaction without reading data
     *               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
     * @param timeout in milliseconds, 0 is infinite
     * @return length of data transferred (or zero) for success,
     * @return length of data transferred (or zero) for success,
     * or negative value for failure
     * or negative value for failure
@@ -239,7 +242,10 @@ public class UsbDeviceConnection {
     * @param endpoint the endpoint for this transaction
     * @param endpoint the endpoint for this transaction
     * @param buffer buffer for data to send or receive
     * @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 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
     * @param timeout in milliseconds, 0 is infinite
     * @return length of data transferred (or zero) for success,
     * @return length of data transferred (or zero) for success,
     * or negative value for failure
     * or negative value for failure
@@ -247,6 +253,10 @@ public class UsbDeviceConnection {
    public int bulkTransfer(UsbEndpoint endpoint,
    public int bulkTransfer(UsbEndpoint endpoint,
            byte[] buffer, int offset, int length, int timeout) {
            byte[] buffer, int offset, int length, int timeout) {
        checkBounds(buffer, offset, length);
        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);
        return native_bulk_request(endpoint.getAddress(), buffer, offset, length, timeout);
    }
    }


+20 −6
Original line number Original line Diff line number Diff line
@@ -17,6 +17,7 @@
package android.hardware.usb;
package android.hardware.usb;


import android.annotation.Nullable;
import android.annotation.Nullable;
import android.os.Build;
import android.util.Log;
import android.util.Log;


import com.android.internal.util.Preconditions;
import com.android.internal.util.Preconditions;
@@ -43,7 +44,7 @@ public class UsbRequest {
    private static final String TAG = "UsbRequest";
    private static final String TAG = "UsbRequest";


    // From drivers/usb/core/devio.c
    // 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
    // used by the JNI code
    private long mNativeContext;
    private long mNativeContext;
@@ -175,7 +176,9 @@ public class UsbRequest {
     *               capacity will be ignored. Once the request
     *               capacity will be ignored. Once the request
     *               {@link UsbDeviceConnection#requestWait() is processed} the position will be set
     *               {@link UsbDeviceConnection#requestWait() is processed} the position will be set
     *               to the number of bytes read/written.
     *               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
     * @return true if the queueing operation succeeded
     *
     *
@@ -186,6 +189,11 @@ public class UsbRequest {
        boolean out = (mEndpoint.getDirection() == UsbConstants.USB_DIR_OUT);
        boolean out = (mEndpoint.getDirection() == UsbConstants.USB_DIR_OUT);
        boolean result;
        boolean result;


        if (mConnection.getContext().getApplicationInfo().targetSdkVersion < Build.VERSION_CODES.P
                && length > MAX_USBFS_BUFFER_SIZE) {
            length = MAX_USBFS_BUFFER_SIZE;
        }

        synchronized (mLock) {
        synchronized (mLock) {
            // save our buffer for when the request has completed
            // save our buffer for when the request has completed
            mBuffer = buffer;
            mBuffer = buffer;
@@ -222,7 +230,10 @@ public class UsbRequest {
     *               of the buffer is undefined until the request is returned by
     *               of the buffer is undefined until the request is returned by
     *               {@link UsbDeviceConnection#requestWait}. If the request failed the buffer
     *               {@link UsbDeviceConnection#requestWait}. If the request failed the buffer
     *               will be unchanged; if the request succeeded the position of the buffer is
     *               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
     * @return true if the queueing operation succeeded
     */
     */
@@ -244,9 +255,12 @@ public class UsbRequest {
                mIsUsingNewQueue = true;
                mIsUsingNewQueue = true;
                wasQueued = native_queue(null, 0, 0);
                wasQueued = native_queue(null, 0, 0);
            } else {
            } else {
                if (mConnection.getContext().getApplicationInfo().targetSdkVersion
                        < Build.VERSION_CODES.P) {
                    // Can only send/receive MAX_USBFS_BUFFER_SIZE bytes at once
                    // Can only send/receive MAX_USBFS_BUFFER_SIZE bytes at once
                    Preconditions.checkArgumentInRange(buffer.remaining(), 0, MAX_USBFS_BUFFER_SIZE,
                    Preconditions.checkArgumentInRange(buffer.remaining(), 0, MAX_USBFS_BUFFER_SIZE,
                            "number of remaining bytes");
                            "number of remaining bytes");
                }


                // Can not receive into read-only buffers.
                // Can not receive into read-only buffers.
                Preconditions.checkArgument(!(buffer.isReadOnly() && !isSend), "buffer can not be "
                Preconditions.checkArgument(!(buffer.isReadOnly() && !isSend), "buffer can not be "