Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Fix: Transfer fails under high load #30

Merged
merged 1 commit into from
Apr 11, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,7 @@
import android.bluetooth.BluetoothGattDescriptor;
import android.bluetooth.BluetoothGattService;
import android.bluetooth.BluetoothProfile;
import android.bluetooth.BluetoothStatusCodes;
import android.content.BroadcastReceiver;
import android.content.Context;
import android.content.Intent;
Expand Down Expand Up @@ -806,17 +807,19 @@ public void configureAsCentralDevice() {
}

@Override
public void transferData(@NonNull byte[] writeBuffer) throws SecurityException {
public boolean transferData(@NonNull byte[] writeBuffer) throws SecurityException {
try {
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.TIRAMISU) {
bluetoothGatt.writeCharacteristic(midiOutputCharacteristic, writeBuffer, BluetoothGattCharacteristic.WRITE_TYPE_NO_RESPONSE);
int result = bluetoothGatt.writeCharacteristic(midiOutputCharacteristic, writeBuffer, BluetoothGattCharacteristic.WRITE_TYPE_NO_RESPONSE);
return result == BluetoothStatusCodes.SUCCESS;
} else {
midiOutputCharacteristic.setValue(writeBuffer);
bluetoothGatt.writeCharacteristic(midiOutputCharacteristic);
return bluetoothGatt.writeCharacteristic(midiOutputCharacteristic);
}
} catch (Throwable ignored) {
// android.os.DeadObjectException will be thrown
// ignore it
return false;
}
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -20,8 +20,9 @@ public abstract class MidiOutputDevice {
* Transfer data
*
* @param writeBuffer byte array to write
* @return true if transfer succeed
*/
protected abstract void transferData(@NonNull byte[] writeBuffer);
protected abstract boolean transferData(@NonNull byte[] writeBuffer);

/**
* Obtains the device name
Expand Down Expand Up @@ -79,14 +80,16 @@ public void run() {
while (transferDataThreadAlive && isRunning) {
synchronized (transferDataStream) {
if (writtenDataCount > 0) {
transferData(transferDataStream.toByteArray());
transferDataStream.reset();
writtenDataCount = 0;
if (transferData(transferDataStream.toByteArray())) {
// reset the stream if transfer succeed
transferDataStream.reset();
writtenDataCount = 0;
}
}
}

try {
Thread.sleep(10);
Thread.sleep(10); // BluetoothGatt.WRITE_CHARACTERISTIC_TIME_TO_WAIT
} catch (InterruptedException ignored) {
}
}
Expand Down Expand Up @@ -238,7 +241,16 @@ public final void sendMidiSystemExclusive(@NonNull byte[] systemExclusive) {
writeBuffer[0] = (byte) (0x80 | ((timestamp >> 7) & 0x3f));

// immediately transfer data
transferData(writeBuffer);
while (true) {
if (transferData(writeBuffer)) {
break;
}

try {
Thread.sleep(10); // BluetoothGatt.WRITE_CHARACTERISTIC_TIME_TO_WAIT
} catch (InterruptedException ignored) {
}
}

timestamp = System.currentTimeMillis() % MAX_TIMESTAMP;
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,7 @@
import android.bluetooth.BluetoothGattService;
import android.bluetooth.BluetoothManager;
import android.bluetooth.BluetoothProfile;
import android.bluetooth.BluetoothStatusCodes;
import android.bluetooth.le.AdvertiseCallback;
import android.bluetooth.le.AdvertiseData;
import android.bluetooth.le.AdvertiseSettings;
Expand Down Expand Up @@ -707,13 +708,18 @@ public String getModel() {
}

@Override
public void transferData(@NonNull byte[] writeBuffer) throws SecurityException {
midiOutputCharacteristic.setValue(writeBuffer);

public boolean transferData(@NonNull byte[] writeBuffer) throws SecurityException {
try {
bluetoothGattServer.notifyCharacteristicChanged(bluetoothDevice, midiOutputCharacteristic, false);
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.TIRAMISU) {
int result = bluetoothGattServer.notifyCharacteristicChanged(bluetoothDevice, midiOutputCharacteristic, false, writeBuffer);
return result == BluetoothStatusCodes.SUCCESS;
} else {
midiOutputCharacteristic.setValue(writeBuffer);
return bluetoothGattServer.notifyCharacteristicChanged(bluetoothDevice, midiOutputCharacteristic, false);
}
} catch (Throwable ignored) {
// ignore it
return false;
}
}

Expand Down
Loading