1
0
mirror of https://codeberg.org/Freeyourgadget/Gadgetbridge synced 2024-08-16 20:31:00 +02:00

Pebble 2: fixes for experimental client only gatt code

This basically makes sure that
- only one gatt write operation is in progress
- data is not sent from within callbacks to prevent a deadlock when waiting for a nre callback that cant happen yet beause the current has not been retuned
This commit is contained in:
Andreas Shimokawa 2018-05-11 13:21:40 +02:00
parent f6131772d6
commit cdf6039d4c
3 changed files with 50 additions and 23 deletions

View File

@ -28,6 +28,7 @@ import org.slf4j.LoggerFactory;
import java.lang.reflect.Method;
import java.util.UUID;
import java.util.concurrent.CountDownLatch;
import nodomain.freeyourgadget.gadgetbridge.GBApplication;
import nodomain.freeyourgadget.gadgetbridge.util.GB;
@ -62,6 +63,8 @@ class PebbleGATTClient extends BluetoothGattCallback {
private boolean removeBond = false;
private BluetoothGatt mBluetoothGatt;
private CountDownLatch mWaitWriteCompleteLatch;
PebbleGATTClient(PebbleLESupport pebbleLESupport, Context context, BluetoothDevice btDevice) {
mContext = context;
mPebbleLESupport = pebbleLESupport;
@ -119,9 +122,16 @@ class PebbleGATTClient extends BluetoothGattCallback {
if (!mPebbleLESupport.isExpectedDevice(gatt.getDevice())) {
return;
}
LOG.info("onCharacteristicWrite() " + characteristic.getUuid());
if (characteristic.getUuid().equals(PAIRING_TRIGGER_CHARACTERISTIC) || characteristic.getUuid().equals(CONNECTIVITY_CHARACTERISTIC)) {
if (characteristic.getUuid().equals(PPOGATT_CHARACTERISTIC_WRITE)) {
if (status != BluetoothGatt.GATT_SUCCESS) {
LOG.error("something went wrong when writing to PPoGATT characteristics");
}
if (mWaitWriteCompleteLatch != null) {
mWaitWriteCompleteLatch.countDown();
} else {
LOG.warn("mWaitWriteCompleteLatch is null!");
}
} else if (characteristic.getUuid().equals(PAIRING_TRIGGER_CHARACTERISTIC) || characteristic.getUuid().equals(CONNECTIVITY_CHARACTERISTIC)) {
//mBtDevice.createBond(); // did not work when last tried
if (oldPebble) {
@ -266,13 +276,20 @@ class PebbleGATTClient extends BluetoothGattCallback {
}
synchronized void sendDataToPebble(byte[] data) {
mWaitWriteCompleteLatch = new CountDownLatch(1);
writeCharacteristics.setValue(data.clone());
mBluetoothGatt.writeCharacteristic(writeCharacteristics);
}
synchronized void sendAckToPebble(int serial) {
writeCharacteristics.setValue(new byte[]{(byte) (((serial << 3) | 1) & 0xff)});
mBluetoothGatt.writeCharacteristic(writeCharacteristics);
boolean success = mBluetoothGatt.writeCharacteristic(writeCharacteristics);
if (!success) {
LOG.error("could not send data to pebble (error writing characteristic)");
} else {
try {
mWaitWriteCompleteLatch.await();
} catch (InterruptedException e) {
LOG.warn("interrupted while waiting for write complete latch");
}
}
mWaitWriteCompleteLatch = null;
}
public void close() {

View File

@ -52,7 +52,9 @@ class PebbleGATTServer extends BluetoothGattServerCallback {
boolean initialize() {
BluetoothManager bluetoothManager = (BluetoothManager) mContext.getSystemService(Context.BLUETOOTH_SERVICE);
if (bluetoothManager == null) {
return false;
}
mBluetoothGattServer = bluetoothManager.openGattServer(mContext, this);
if (mBluetoothGattServer == null) {
return false;
@ -76,12 +78,6 @@ class PebbleGATTServer extends BluetoothGattServerCallback {
mBluetoothGattServer.notifyCharacteristicChanged(mBtDevice, writeCharacteristics, false);
}
synchronized void sendAckToPebble(int serial) {
writeCharacteristics.setValue(new byte[]{(byte) (((serial << 3) | 1) & 0xff)});
mBluetoothGattServer.notifyCharacteristicChanged(mBtDevice, writeCharacteristics, false);
}
public void onCharacteristicReadRequest(BluetoothDevice device, int requestId, int offset, BluetoothGattCharacteristic characteristic) {
if (!mPebbleLESupport.isExpectedDevice(device)) {
return;

View File

@ -18,6 +18,8 @@ package nodomain.freeyourgadget.gadgetbridge.service.devices.pebble.ble;
import android.bluetooth.BluetoothDevice;
import android.content.Context;
import android.os.Handler;
import android.os.HandlerThread;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
@ -39,9 +41,11 @@ public class PebbleLESupport {
private PipedOutputStream mPipedOutputStream;
private int mMTU = 20;
private int mMTULimit = Integer.MAX_VALUE;
public boolean clientOnly = false; // currently broken, and only possible for Pebble 2
public boolean clientOnly = false; // currently experimental, and only possible for Pebble 2
private boolean mIsConnected = false;
private CountDownLatch mPPAck;
private HandlerThread mWriteHandlerThread;
private Handler mWriteHandler;
public PebbleLESupport(Context context, final BluetoothDevice btDevice, PipedInputStream pipedInputStream, PipedOutputStream pipedOutputStream) throws IOException {
mBtDevice = btDevice;
@ -53,6 +57,11 @@ public class PebbleLESupport {
} catch (IOException e) {
LOG.warn("could not connect input stream");
}
mWriteHandlerThread = new HandlerThread("write handler thread");
mWriteHandlerThread.start();
mWriteHandler = new Handler(mWriteHandlerThread.getLooper());
mMTULimit = GBApplication.getPrefs().getInt("pebble_mtu_limit", 512);
mMTULimit = Math.max(mMTULimit, 20);
mMTULimit = Math.min(mMTULimit, 512);
@ -102,6 +111,9 @@ public class PebbleLESupport {
mPipedOutputStream.close();
} catch (IOException ignore) {
}
if (mWriteHandlerThread != null) {
mWriteHandlerThread.quit();
}
}
private synchronized void createPipedInputReader() {
@ -166,19 +178,21 @@ public class PebbleLESupport {
}
private void sendAckToPebble(int serial) {
if (mPebbleGATTServer != null) {
mPebbleGATTServer.sendAckToPebble(serial);
} else {
mPebbleGATTClient.sendAckToPebble(serial);
}
sendDataToPebble(new byte[]{(byte) (((serial << 3) | 1) & 0xff)});
}
private void sendDataToPebble(byte[] bytes) {
private synchronized void sendDataToPebble(final byte[] bytes) {
if (mPebbleGATTServer != null) {
mPebbleGATTServer.sendDataToPebble(bytes);
} else {
// For now only in experimental client only code
mWriteHandler.post(new Runnable() {
@Override
public void run() {
mPebbleGATTClient.sendDataToPebble(bytes);
}
});
}
}
private class PipeReader extends Thread {