summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--services/usb/java/com/android/server/usb/UsbDirectMidiDevice.java62
1 files changed, 53 insertions, 9 deletions
diff --git a/services/usb/java/com/android/server/usb/UsbDirectMidiDevice.java b/services/usb/java/com/android/server/usb/UsbDirectMidiDevice.java
index 2ae328b0d8e9..394d6e774aa1 100644
--- a/services/usb/java/com/android/server/usb/UsbDirectMidiDevice.java
+++ b/services/usb/java/com/android/server/usb/UsbDirectMidiDevice.java
@@ -19,6 +19,7 @@ package com.android.server.usb;
import android.annotation.NonNull;
import android.content.Context;
import android.hardware.usb.UsbConfiguration;
+import android.hardware.usb.UsbConstants;
import android.hardware.usb.UsbDevice;
import android.hardware.usb.UsbDeviceConnection;
import android.hardware.usb.UsbEndpoint;
@@ -76,10 +77,10 @@ public final class UsbDirectMidiDevice implements Closeable {
// event schedulers for each input port of the physical device
private MidiEventScheduler[] mEventSchedulers;
- // Arbitrary number for timeout to not continue sending to
- // an inactive device. This number tries to balances the number
- // of cycles and not being permanently stuck.
- private static final int BULK_TRANSFER_TIMEOUT_MILLISECONDS = 10;
+ // Timeout for sending a packet to a device.
+ // If bulkTransfer times out, retry sending the packet up to 20 times.
+ private static final int BULK_TRANSFER_TIMEOUT_MILLISECONDS = 50;
+ private static final int BULK_TRANSFER_NUMBER_OF_RETRIES = 20;
// Arbitrary number for timeout when closing a thread
private static final int THREAD_JOIN_TIMEOUT_MILLISECONDS = 200;
@@ -386,10 +387,15 @@ public final class UsbDirectMidiDevice implements Closeable {
break;
}
final UsbRequest response = connectionFinal.requestWait();
- if (response != request) {
- Log.w(TAG, "Unexpected response");
+ if (response == null) {
+ Log.w(TAG, "Response is null");
break;
}
+ if (request != response) {
+ Log.w(TAG, "Skipping response");
+ continue;
+ }
+
int bytesRead = byteBuffer.position();
if (bytesRead > 0) {
@@ -513,9 +519,47 @@ public final class UsbDirectMidiDevice implements Closeable {
convertedArray.length);
}
- connectionFinal.bulkTransfer(endpointFinal, convertedArray,
- convertedArray.length,
- BULK_TRANSFER_TIMEOUT_MILLISECONDS);
+ boolean isInterrupted = false;
+ // Split the packet into multiple if they are greater than the
+ // endpoint's max packet size.
+ for (int curPacketStart = 0;
+ curPacketStart < convertedArray.length &&
+ isInterrupted == false;
+ curPacketStart += endpointFinal.getMaxPacketSize()) {
+ int transferResult = -1;
+ int retryCount = 0;
+ int curPacketSize = Math.min(endpointFinal.getMaxPacketSize(),
+ convertedArray.length - curPacketStart);
+
+ // Keep trying to send the packet until the result is
+ // successful or until the retry limit is reached.
+ while (transferResult < 0 && retryCount <=
+ BULK_TRANSFER_NUMBER_OF_RETRIES) {
+ transferResult = connectionFinal.bulkTransfer(
+ endpointFinal,
+ convertedArray,
+ curPacketStart,
+ curPacketSize,
+ BULK_TRANSFER_TIMEOUT_MILLISECONDS);
+ retryCount++;
+
+ if (Thread.currentThread().interrupted()) {
+ Log.w(TAG, "output thread interrupted after send");
+ isInterrupted = true;
+ break;
+ }
+ if (transferResult < 0) {
+ Log.d(TAG, "retrying packet. retryCount = "
+ + retryCount + " result = " + transferResult);
+ if (retryCount > BULK_TRANSFER_NUMBER_OF_RETRIES) {
+ Log.w(TAG, "Skipping packet because timeout");
+ }
+ }
+ }
+ }
+ if (isInterrupted == true) {
+ break;
+ }
eventSchedulerFinal.addEventToPool(event);
}
} catch (NullPointerException e) {