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

Commit 3688b228 authored by Robert Wu's avatar Robert Wu
Browse files

Increase Bluetooth MIDI maximum size

The current Bluetooth MIDI max size is 20, so certain keyboard
creators like Yamaha are complaining at the number of packets
sent at a time. This cl changes the max size to 512 bytes.

Previously, a 2D array of size 20 was created. With this change,
this 2D array is no longer created. Instead, the last array is
cached. Only when a differently-sized packet is created, is new
called on the array.

Bug: 147950483
Test: Connected to Alesis drums via bluetooth and tested both input and
output. Also verified that BluetoothGatt: configureMTU() was called with
an MTU of 512 and the omMtuChanged callback returned a valid status

Change-Id: Ia10b81ffe51277d0565631fd28e71c7c8ca884ae
parent 4cffc46a
Loading
Loading
Loading
Loading
+28 −12
Original line number Diff line number Diff line
@@ -39,7 +39,6 @@ import com.android.internal.midi.MidiEventScheduler.MidiEvent;
import libcore.io.IoUtils;

import java.io.IOException;
import java.util.List;
import java.util.UUID;

/**
@@ -50,7 +49,8 @@ public final class BluetoothMidiDevice {
    private static final String TAG = "BluetoothMidiDevice";
    private static final boolean DEBUG = false;

    private static final int MAX_PACKET_SIZE = 20;
    private static final int DEFAULT_PACKET_SIZE = 20;
    private static final int MAX_PACKET_SIZE = 512;

    //  Bluetooth MIDI Gatt service UUID
    private static final UUID MIDI_SERVICE = UUID.fromString(
@@ -103,6 +103,11 @@ public final class BluetoothMidiDevice {
                Log.d(TAG, "Connected to GATT server.");
                Log.d(TAG, "Attempting to start service discovery:" +
                        mBluetoothGatt.discoverServices());
                if (!mBluetoothGatt.requestMtu(MAX_PACKET_SIZE)) {
                    Log.e(TAG, "request mtu failed");
                    mPacketEncoder.setMaxPacketSize(DEFAULT_PACKET_SIZE);
                    mPacketDecoder.setMaxPacketSize(DEFAULT_PACKET_SIZE);
                }
            } else if (newState == BluetoothProfile.STATE_DISCONNECTED) {
                Log.i(TAG, "Disconnected from GATT server.");
                close();
@@ -182,21 +187,27 @@ public final class BluetoothMidiDevice {
            }
            mPacketDecoder.decodePacket(characteristic.getValue(), mOutputReceiver);
        }

        @Override
        public void onMtuChanged(BluetoothGatt gatt, int mtu, int status) {
            Log.d(TAG, "onMtuChanged callback received. mtu: " + mtu + ", status: " + status);
            if (status == BluetoothGatt.GATT_SUCCESS) {
                mPacketEncoder.setMaxPacketSize(Math.min(mtu, MAX_PACKET_SIZE));
                mPacketDecoder.setMaxPacketSize(Math.min(mtu, MAX_PACKET_SIZE));
            } else {
                mPacketEncoder.setMaxPacketSize(DEFAULT_PACKET_SIZE);
                mPacketDecoder.setMaxPacketSize(DEFAULT_PACKET_SIZE);
            }
        }
    };

    // This receives MIDI data that has already been passed through our MidiEventScheduler
    // and has been normalized by our MidiFramer.

    private class PacketReceiver implements PacketEncoder.PacketReceiver {
        // buffers of every possible packet size
        private final byte[][] mWriteBuffers;
        private byte[] mCachedBuffer;

        public PacketReceiver() {
            // Create buffers of every possible packet size
            mWriteBuffers = new byte[MAX_PACKET_SIZE + 1][];
            for (int i = 0; i <= MAX_PACKET_SIZE; i++) {
                mWriteBuffers[i] = new byte[i];
            }
        }

        @Override
@@ -205,9 +216,14 @@ public final class BluetoothMidiDevice {
                Log.w(TAG, "not ready to send packet yet");
                return;
            }
            byte[] writeBuffer = mWriteBuffers[count];
            System.arraycopy(buffer, 0, writeBuffer, 0, count);
            mCharacteristic.setValue(writeBuffer);

            // Cache the previous buffer for writePacket so buffers aren't
            // consistently created if the buffer sizes are consistent.
            if ((mCachedBuffer == null) || (mCachedBuffer.length != count)) {
                mCachedBuffer = new byte[count];
            }
            System.arraycopy(buffer, 0, mCachedBuffer, 0, count);
            mCharacteristic.setValue(mCachedBuffer);
            if (DEBUG) {
                logByteArray("Sent ", mCharacteristic.getValue(), 0,
                       mCharacteristic.getValue().length);
+11 −1
Original line number Diff line number Diff line
@@ -30,6 +30,7 @@ public class BluetoothPacketDecoder extends PacketDecoder {
    private static final String TAG = "BluetoothPacketDecoder";

    private final byte[] mBuffer;
    private int mMaxPacketSize;
    private int mBytesInBuffer;
    private MidiBtleTimeTracker mTimeTracker;

@@ -42,6 +43,14 @@ public class BluetoothPacketDecoder extends PacketDecoder {

    public BluetoothPacketDecoder(int maxPacketSize) {
        mBuffer = new byte[maxPacketSize];
        setMaxPacketSize(maxPacketSize);
    }

    /**
     * Dynamically sets the maximum packet size
     */
    public void setMaxPacketSize(int maxPacketSize) {
        mMaxPacketSize = Math.min(maxPacketSize, mBuffer.length);
    }

    private void flushOutput(MidiReceiver receiver) {
@@ -83,6 +92,7 @@ public class BluetoothPacketDecoder extends PacketDecoder {
        int previousLowTimestamp = 0;
        int currentTimestamp = highTimestamp | mLowTimestamp;

        int curMaxPacketSize = mMaxPacketSize;
        // Iterate through the rest of the packet, separating MIDI data from timestamps.
        for (int i = 1; i < buffer.length; i++) {
            byte b = buffer[i];
@@ -113,7 +123,7 @@ public class BluetoothPacketDecoder extends PacketDecoder {
            } else {
                lastWasTimestamp = false;
                // Flush if full before adding more data.
                if (mBytesInBuffer == mBuffer.length) {
                if (mBytesInBuffer >= curMaxPacketSize) {
                    flushOutput(receiver);
                }
                mBuffer[mBytesInBuffer++] = b;
+16 −4
Original line number Diff line number Diff line
@@ -45,6 +45,8 @@ public class BluetoothPacketEncoder extends PacketEncoder {
    private int mPacketTimestamp;
    // current running status, or zero if none
    private byte mRunningStatus;
    // max size of a packet
    private int mMaxPacketSize;

    private boolean mWritePending;

@@ -86,7 +88,7 @@ public class BluetoothPacketEncoder extends PacketEncoder {
                if (needsTimestamp) bytesNeeded++;  // add one for timestamp byte
                if (status == mRunningStatus) bytesNeeded--;    // subtract one for status byte

                if (mAccumulatedBytes + bytesNeeded > mAccumulationBuffer.length) {
                if (mAccumulatedBytes + bytesNeeded > mMaxPacketSize) {
                    // write out our data if there is no more room
                    // if necessary, block until previous packet is sent
                    flushLocked(true);
@@ -112,14 +114,14 @@ public class BluetoothPacketEncoder extends PacketEncoder {
                    int remaining = (hasSysExEnd ? count - 1 : count);

                    while (remaining > 0) {
                        if (mAccumulatedBytes == mAccumulationBuffer.length) {
                        if (mAccumulatedBytes == mMaxPacketSize) {
                            // write out our data if there is no more room
                            // if necessary, block until previous packet is sent
                            flushLocked(true);
                            appendHeader(milliTimestamp);
                        }

                        int copy = mAccumulationBuffer.length - mAccumulatedBytes;
                        int copy = mMaxPacketSize - mAccumulatedBytes;
                        if (copy > remaining) copy = remaining;
                        System.arraycopy(msg, offset, mAccumulationBuffer, mAccumulatedBytes, copy);
                        mAccumulatedBytes += copy;
@@ -129,7 +131,7 @@ public class BluetoothPacketEncoder extends PacketEncoder {

                    if (hasSysExEnd) {
                        // SysEx End command must be preceeded by a timestamp byte
                        if (mAccumulatedBytes + 2 > mAccumulationBuffer.length) {
                        if (mAccumulatedBytes + 2 > mMaxPacketSize) {
                            // write out our data if there is no more room
                            // if necessary, block until previous packet is sent
                            flushLocked(true);
@@ -182,6 +184,16 @@ public class BluetoothPacketEncoder extends PacketEncoder {
    public BluetoothPacketEncoder(PacketReceiver packetReceiver, int maxPacketSize) {
        mPacketReceiver = packetReceiver;
        mAccumulationBuffer = new byte[maxPacketSize];
        setMaxPacketSize(maxPacketSize);
    }

    /**
     * Dynamically sets the maximum packet size
     */
    public void setMaxPacketSize(int maxPacketSize) {
        synchronized (mLock) {
            mMaxPacketSize = Math.min(maxPacketSize, mAccumulationBuffer.length);
        }
    }

    @Override