USB MIDI: Create encoder per output port

UsbMidiEncoder is not thread-safe. Therefore, each output port
should use its own encoder.

Bug: 225884009
Test: MidiKeyboard/MidiScope on both MIDI 2.0 and MIDI 1.0 paths.
Test: Verified M-Audio Keyboard with only input has the correct logs.
Change-Id: I43bd7381982403766b7f37c22d55ef5d19013120
This commit is contained in:
Robert Wu
2022-03-21 15:29:02 +00:00
parent f48450217c
commit d338c3c8f8
2 changed files with 20 additions and 5 deletions

View File

@@ -84,7 +84,7 @@ public final class UsbDirectMidiDevice implements Closeable {
private final Object mLock = new Object();
private boolean mIsOpen;
private final UsbMidiPacketConverter mUsbMidiPacketConverter = new UsbMidiPacketConverter();
private UsbMidiPacketConverter mUsbMidiPacketConverter;
private final MidiDeviceServer.Callback mCallback = new MidiDeviceServer.Callback() {
@@ -264,6 +264,11 @@ public final class UsbDirectMidiDevice implements Closeable {
Log.d(TAG, "openLocked()");
UsbManager manager = mContext.getSystemService(UsbManager.class);
// Converting from raw MIDI to USB MIDI is not thread-safe.
// UsbMidiPacketConverter creates a converter from raw MIDI
// to USB MIDI for each USB output.
mUsbMidiPacketConverter = new UsbMidiPacketConverter(mNumOutputs);
mUsbDeviceConnections = new ArrayList<UsbDeviceConnection>(mUsbInterfaces.size());
mInputUsbEndpoints = new ArrayList<ArrayList<UsbEndpoint>>(mUsbInterfaces.size());
mOutputUsbEndpoints = new ArrayList<ArrayList<UsbEndpoint>>(mUsbInterfaces.size());
@@ -415,7 +420,7 @@ public final class UsbDirectMidiDevice implements Closeable {
} else {
convertedArray =
mUsbMidiPacketConverter.rawMidiToUsbMidi(
event.data, event.count);
event.data, event.count, portFinal);
}
if (DEBUG) {
@@ -518,6 +523,8 @@ public final class UsbDirectMidiDevice implements Closeable {
mInputUsbEndpoints = null;
mOutputUsbEndpoints = null;
mUsbMidiPacketConverter = null;
mIsOpen = false;
}

View File

@@ -74,8 +74,15 @@ public class UsbMidiPacketConverter {
private static final byte SYSEX_START_EXCLUSIVE = (byte) 0xF0;
private static final byte SYSEX_END_EXCLUSIVE = (byte) 0xF7;
private UsbMidiEncoder mUsbMidiEncoder = new UsbMidiEncoder();
private UsbMidiDecoder mUsbMidiDecoder = new UsbMidiDecoder();
private UsbMidiEncoder[] mUsbMidiEncoders;
public UsbMidiPacketConverter(int numEncoders) {
mUsbMidiEncoders = new UsbMidiEncoder[numEncoders];
for (int i = 0; i < numEncoders; i++) {
mUsbMidiEncoders[i] = new UsbMidiEncoder();
}
}
/**
* Converts a USB MIDI array into a raw MIDI array.
@@ -93,10 +100,11 @@ public class UsbMidiPacketConverter {
*
* @param midiBytes the raw MIDI bytes to convert
* @param size the size of usbMidiBytes
* @param encoderId which encoder to use
* @return byte array of USB MIDI packets
*/
public byte[] rawMidiToUsbMidi(byte[] midiBytes, int size) {
return mUsbMidiEncoder.encode(midiBytes, size);
public byte[] rawMidiToUsbMidi(byte[] midiBytes, int size, int encoderId) {
return mUsbMidiEncoders[encoderId].encode(midiBytes, size);
}
private class UsbMidiDecoder {