Merge "USB MIDI: Use Thread.interrupt() to close threads" into tm-dev
This commit is contained in:
@@ -80,9 +80,13 @@ public final class UsbDirectMidiDevice implements Closeable {
|
|||||||
// of cycles and not being permanently stuck.
|
// of cycles and not being permanently stuck.
|
||||||
private static final int BULK_TRANSFER_TIMEOUT_MILLISECONDS = 10;
|
private static final int BULK_TRANSFER_TIMEOUT_MILLISECONDS = 10;
|
||||||
|
|
||||||
|
// Arbitrary number for timeout when closing a thread
|
||||||
|
private static final int THREAD_JOIN_TIMEOUT_MILLISECONDS = 50;
|
||||||
|
|
||||||
private ArrayList<UsbDeviceConnection> mUsbDeviceConnections;
|
private ArrayList<UsbDeviceConnection> mUsbDeviceConnections;
|
||||||
private ArrayList<ArrayList<UsbEndpoint>> mInputUsbEndpoints;
|
private ArrayList<ArrayList<UsbEndpoint>> mInputUsbEndpoints;
|
||||||
private ArrayList<ArrayList<UsbEndpoint>> mOutputUsbEndpoints;
|
private ArrayList<ArrayList<UsbEndpoint>> mOutputUsbEndpoints;
|
||||||
|
private ArrayList<Thread> mThreads;
|
||||||
|
|
||||||
private UsbMidiBlockParser mMidiBlockParser = new UsbMidiBlockParser();
|
private UsbMidiBlockParser mMidiBlockParser = new UsbMidiBlockParser();
|
||||||
private int mDefaultMidiProtocol = MidiDeviceInfo.PROTOCOL_UMP_MIDI_1_0_UP_TO_64_BITS;
|
private int mDefaultMidiProtocol = MidiDeviceInfo.PROTOCOL_UMP_MIDI_1_0_UP_TO_64_BITS;
|
||||||
@@ -273,9 +277,10 @@ public final class UsbDirectMidiDevice implements Closeable {
|
|||||||
// to USB MIDI for each USB output.
|
// to USB MIDI for each USB output.
|
||||||
mUsbMidiPacketConverter = new UsbMidiPacketConverter(mNumOutputs);
|
mUsbMidiPacketConverter = new UsbMidiPacketConverter(mNumOutputs);
|
||||||
|
|
||||||
mUsbDeviceConnections = new ArrayList<UsbDeviceConnection>(mUsbInterfaces.size());
|
mUsbDeviceConnections = new ArrayList<UsbDeviceConnection>();
|
||||||
mInputUsbEndpoints = new ArrayList<ArrayList<UsbEndpoint>>(mUsbInterfaces.size());
|
mInputUsbEndpoints = new ArrayList<ArrayList<UsbEndpoint>>();
|
||||||
mOutputUsbEndpoints = new ArrayList<ArrayList<UsbEndpoint>>(mUsbInterfaces.size());
|
mOutputUsbEndpoints = new ArrayList<ArrayList<UsbEndpoint>>();
|
||||||
|
mThreads = new ArrayList<Thread>();
|
||||||
|
|
||||||
for (int interfaceIndex = 0; interfaceIndex < mUsbInterfaces.size(); interfaceIndex++) {
|
for (int interfaceIndex = 0; interfaceIndex < mUsbInterfaces.size(); interfaceIndex++) {
|
||||||
ArrayList<UsbEndpoint> inputEndpoints = new ArrayList<UsbEndpoint>();
|
ArrayList<UsbEndpoint> inputEndpoints = new ArrayList<UsbEndpoint>();
|
||||||
@@ -327,7 +332,7 @@ public final class UsbDirectMidiDevice implements Closeable {
|
|||||||
mInputUsbEndpoints.get(connectionIndex).get(endpointIndex);
|
mInputUsbEndpoints.get(connectionIndex).get(endpointIndex);
|
||||||
final int portFinal = portNumber;
|
final int portFinal = portNumber;
|
||||||
|
|
||||||
new Thread("UsbDirectMidiDevice input thread " + portFinal) {
|
Thread newThread = new Thread("UsbDirectMidiDevice input thread " + portFinal) {
|
||||||
@Override
|
@Override
|
||||||
public void run() {
|
public void run() {
|
||||||
final UsbRequest request = new UsbRequest();
|
final UsbRequest request = new UsbRequest();
|
||||||
@@ -335,9 +340,12 @@ public final class UsbDirectMidiDevice implements Closeable {
|
|||||||
request.initialize(connectionFinal, endpointFinal);
|
request.initialize(connectionFinal, endpointFinal);
|
||||||
byte[] inputBuffer = new byte[endpointFinal.getMaxPacketSize()];
|
byte[] inputBuffer = new byte[endpointFinal.getMaxPacketSize()];
|
||||||
while (true) {
|
while (true) {
|
||||||
|
if (Thread.currentThread().interrupted()) {
|
||||||
|
Log.w(TAG, "input thread interrupted");
|
||||||
|
break;
|
||||||
|
}
|
||||||
// Record time of event immediately after waking.
|
// Record time of event immediately after waking.
|
||||||
long timestamp = System.nanoTime();
|
long timestamp = System.nanoTime();
|
||||||
if (!mIsOpen) break;
|
|
||||||
final ByteBuffer byteBuffer = ByteBuffer.wrap(inputBuffer);
|
final ByteBuffer byteBuffer = ByteBuffer.wrap(inputBuffer);
|
||||||
if (!request.queue(byteBuffer)) {
|
if (!request.queue(byteBuffer)) {
|
||||||
Log.w(TAG, "Cannot queue request");
|
Log.w(TAG, "Cannot queue request");
|
||||||
@@ -382,8 +390,9 @@ public final class UsbDirectMidiDevice implements Closeable {
|
|||||||
}
|
}
|
||||||
Log.d(TAG, "input thread exit");
|
Log.d(TAG, "input thread exit");
|
||||||
}
|
}
|
||||||
}.start();
|
};
|
||||||
|
newThread.start();
|
||||||
|
mThreads.add(newThread);
|
||||||
portNumber++;
|
portNumber++;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -402,18 +411,23 @@ public final class UsbDirectMidiDevice implements Closeable {
|
|||||||
final int portFinal = portNumber;
|
final int portFinal = portNumber;
|
||||||
final MidiEventScheduler eventSchedulerFinal = mEventSchedulers[portFinal];
|
final MidiEventScheduler eventSchedulerFinal = mEventSchedulers[portFinal];
|
||||||
|
|
||||||
new Thread("UsbDirectMidiDevice output thread " + portFinal) {
|
Thread newThread = new Thread("UsbDirectMidiDevice output thread " + portFinal) {
|
||||||
@Override
|
@Override
|
||||||
public void run() {
|
public void run() {
|
||||||
while (true) {
|
while (true) {
|
||||||
|
if (Thread.currentThread().interrupted()) {
|
||||||
|
Log.w(TAG, "output thread interrupted");
|
||||||
|
break;
|
||||||
|
}
|
||||||
MidiEvent event;
|
MidiEvent event;
|
||||||
try {
|
try {
|
||||||
event = (MidiEvent) eventSchedulerFinal.waitNextEvent();
|
event = (MidiEvent) eventSchedulerFinal.waitNextEvent();
|
||||||
} catch (InterruptedException e) {
|
} catch (InterruptedException e) {
|
||||||
// try again
|
Log.w(TAG, "event scheduler interrupted");
|
||||||
continue;
|
break;
|
||||||
}
|
}
|
||||||
if (event == null) {
|
if (event == null) {
|
||||||
|
Log.w(TAG, "event is null");
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -446,8 +460,9 @@ public final class UsbDirectMidiDevice implements Closeable {
|
|||||||
}
|
}
|
||||||
Log.d(TAG, "output thread exit");
|
Log.d(TAG, "output thread exit");
|
||||||
}
|
}
|
||||||
}.start();
|
};
|
||||||
|
newThread.start();
|
||||||
|
mThreads.add(newThread);
|
||||||
portNumber++;
|
portNumber++;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -523,6 +538,27 @@ public final class UsbDirectMidiDevice implements Closeable {
|
|||||||
|
|
||||||
private void closeLocked() {
|
private void closeLocked() {
|
||||||
Log.d(TAG, "closeLocked()");
|
Log.d(TAG, "closeLocked()");
|
||||||
|
|
||||||
|
// Send an interrupt signal to threads.
|
||||||
|
for (Thread thread : mThreads) {
|
||||||
|
if (thread != null) {
|
||||||
|
thread.interrupt();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Wait for threads to actually stop.
|
||||||
|
for (Thread thread : mThreads) {
|
||||||
|
if (thread != null) {
|
||||||
|
try {
|
||||||
|
thread.join(THREAD_JOIN_TIMEOUT_MILLISECONDS);
|
||||||
|
} catch (InterruptedException e) {
|
||||||
|
Log.w(TAG, "thread join interrupted");
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
mThreads = null;
|
||||||
|
|
||||||
for (int i = 0; i < mEventSchedulers.length; i++) {
|
for (int i = 0; i < mEventSchedulers.length; i++) {
|
||||||
mMidiInputPortReceivers[i].setReceiver(null);
|
mMidiInputPortReceivers[i].setReceiver(null);
|
||||||
mEventSchedulers[i].close();
|
mEventSchedulers[i].close();
|
||||||
|
|||||||
Reference in New Issue
Block a user