1
0
mirror of https://codeberg.org/Freeyourgadget/Gadgetbridge synced 2024-11-12 21:19:25 +01:00

Initial support for transaction-local GattCallbacks (not used yet)

So that we won't have to mix everything in MiBandSupport
This commit is contained in:
cpfeiffer 2015-08-05 23:24:58 +02:00
parent 495a8cc650
commit b7223c7e86
4 changed files with 119 additions and 22 deletions

View File

@ -0,0 +1,42 @@
package nodomain.freeyourgadget.gadgetbridge.service.btle;
import android.bluetooth.BluetoothGatt;
import android.bluetooth.BluetoothGattCharacteristic;
import android.bluetooth.BluetoothGattDescriptor;
/**
* Base class for GattCallbacks wishing to just implement a few of the methods.
*/
public abstract class AbstractGattCallback implements GattCallback {
@Override
public void onConnectionStateChange(BluetoothGatt gatt, int status, int newState) {
}
@Override
public void onServicesDiscovered(BluetoothGatt gatt) {
}
@Override
public void onCharacteristicRead(BluetoothGatt gatt, BluetoothGattCharacteristic characteristic, int status) {
}
@Override
public void onCharacteristicWrite(BluetoothGatt gatt, BluetoothGattCharacteristic characteristic, int status) {
}
@Override
public void onCharacteristicChanged(BluetoothGatt gatt, BluetoothGattCharacteristic characteristic) {
}
@Override
public void onDescriptorRead(BluetoothGatt gatt, BluetoothGattDescriptor descriptor, int status) {
}
@Override
public void onDescriptorWrite(BluetoothGatt gatt, BluetoothGattDescriptor descriptor, int status) {
}
@Override
public void onReadRemoteRssi(BluetoothGatt gatt, int rssi, int status) {
}
}

View File

@ -9,6 +9,7 @@ import android.bluetooth.BluetoothGattDescriptor;
import android.bluetooth.BluetoothGattService; import android.bluetooth.BluetoothGattService;
import android.bluetooth.BluetoothProfile; import android.bluetooth.BluetoothProfile;
import android.content.Context; import android.content.Context;
import android.support.annotation.Nullable;
import org.slf4j.Logger; import org.slf4j.Logger;
import org.slf4j.LoggerFactory; import org.slf4j.LoggerFactory;
@ -19,9 +20,9 @@ import java.util.concurrent.BlockingQueue;
import java.util.concurrent.CountDownLatch; import java.util.concurrent.CountDownLatch;
import java.util.concurrent.LinkedBlockingQueue; import java.util.concurrent.LinkedBlockingQueue;
import nodomain.freeyourgadget.gadgetbridge.service.DeviceSupport;
import nodomain.freeyourgadget.gadgetbridge.impl.GBDevice; import nodomain.freeyourgadget.gadgetbridge.impl.GBDevice;
import nodomain.freeyourgadget.gadgetbridge.impl.GBDevice.State; import nodomain.freeyourgadget.gadgetbridge.impl.GBDevice.State;
import nodomain.freeyourgadget.gadgetbridge.service.DeviceSupport;
/** /**
* One queue/thread per connectable device. * One queue/thread per connectable device.
@ -49,7 +50,7 @@ public final class BtLEQueue {
private CountDownLatch mWaitForActionResultLatch; private CountDownLatch mWaitForActionResultLatch;
private CountDownLatch mConnectionLatch; private CountDownLatch mConnectionLatch;
private BluetoothGattCharacteristic mWaitCharacteristic; private BluetoothGattCharacteristic mWaitCharacteristic;
private GattCallback mExternalGattCallback; private final InternalGattCallback internalGattCallback;
private Thread dispatchThread = new Thread("GadgetBridge GATT Dispatcher") { private Thread dispatchThread = new Thread("GadgetBridge GATT Dispatcher") {
@ -60,6 +61,8 @@ public final class BtLEQueue {
while (!mDisposed && !mCrashed) { while (!mDisposed && !mCrashed) {
try { try {
Transaction transaction = mTransactions.take(); Transaction transaction = mTransactions.take();
internalGattCallback.setTransactionGattCallback(null);
if (!isConnected()) { if (!isConnected()) {
// TODO: request connection and initialization from the outside and wait until finished // TODO: request connection and initialization from the outside and wait until finished
@ -73,6 +76,7 @@ public final class BtLEQueue {
mConnectionLatch = null; mConnectionLatch = null;
} }
internalGattCallback.setTransactionGattCallback(transaction.getGattCallback());
mAbortTransaction = false; mAbortTransaction = false;
// Run all actions of the transaction until one doesn't succeed // Run all actions of the transaction until one doesn't succeed
for (BtLEAction action : transaction.getActions()) { for (BtLEAction action : transaction.getActions()) {
@ -106,6 +110,7 @@ public final class BtLEQueue {
} finally { } finally {
mWaitForActionResultLatch = null; mWaitForActionResultLatch = null;
mWaitCharacteristic = null; mWaitCharacteristic = null;
internalGattCallback.reset();
} }
} }
LOG.info("Queue Dispatch Thread terminated."); LOG.info("Queue Dispatch Thread terminated.");
@ -115,7 +120,7 @@ public final class BtLEQueue {
public BtLEQueue(BluetoothAdapter bluetoothAdapter, GBDevice gbDevice, GattCallback externalGattCallback, Context context) { public BtLEQueue(BluetoothAdapter bluetoothAdapter, GBDevice gbDevice, GattCallback externalGattCallback, Context context) {
mBluetoothAdapter = bluetoothAdapter; mBluetoothAdapter = bluetoothAdapter;
mGbDevice = gbDevice; mGbDevice = gbDevice;
mExternalGattCallback = externalGattCallback; internalGattCallback = new InternalGattCallback(externalGattCallback);
mContext = context; mContext = context;
dispatchThread.start(); dispatchThread.start();
@ -254,7 +259,25 @@ public final class BtLEQueue {
// Implements callback methods for GATT events that the app cares about. For example, // Implements callback methods for GATT events that the app cares about. For example,
// connection change and services discovered. // connection change and services discovered.
private final BluetoothGattCallback internalGattCallback = new BluetoothGattCallback() { private final class InternalGattCallback extends BluetoothGattCallback {
private @Nullable GattCallback mTransactionGattCallback;
private GattCallback mExternalGattCallback;
public InternalGattCallback(GattCallback externalGattCallback) {
mExternalGattCallback = externalGattCallback;
}
public void setTransactionGattCallback(@Nullable GattCallback callback) {
mTransactionGattCallback = callback;
}
private GattCallback getCallbackToUse() {
if (mTransactionGattCallback != null) {
return mTransactionGattCallback;
}
return mExternalGattCallback;
}
@Override @Override
public void onConnectionStateChange(BluetoothGatt gatt, int status, int newState) { public void onConnectionStateChange(BluetoothGatt gatt, int status, int newState) {
LOG.debug("connection state change, newState: " + newState + getStatusString(status)); LOG.debug("connection state change, newState: " + newState + getStatusString(status));
@ -293,9 +316,9 @@ public final class BtLEQueue {
} }
if (status == BluetoothGatt.GATT_SUCCESS) { if (status == BluetoothGatt.GATT_SUCCESS) {
if (mExternalGattCallback != null) { if (getCallbackToUse() != null) {
// only propagate the successful event // only propagate the successful event
mExternalGattCallback.onServicesDiscovered(gatt); getCallbackToUse().onServicesDiscovered(gatt);
} }
} else { } else {
LOG.warn("onServicesDiscovered received: " + status); LOG.warn("onServicesDiscovered received: " + status);
@ -308,8 +331,8 @@ public final class BtLEQueue {
if (!checkCorrectGattInstance(gatt, "characteristic write")) { if (!checkCorrectGattInstance(gatt, "characteristic write")) {
return; return;
} }
if (mExternalGattCallback != null) { if (getCallbackToUse() != null) {
mExternalGattCallback.onCharacteristicWrite(gatt, characteristic, status); getCallbackToUse().onCharacteristicWrite(gatt, characteristic, status);
} }
checkWaitingCharacteristic(characteristic, status); checkWaitingCharacteristic(characteristic, status);
} }
@ -322,8 +345,8 @@ public final class BtLEQueue {
if (!checkCorrectGattInstance(gatt, "characteristic read")) { if (!checkCorrectGattInstance(gatt, "characteristic read")) {
return; return;
} }
if (mExternalGattCallback != null) { if (getCallbackToUse() != null) {
mExternalGattCallback.onCharacteristicRead(gatt, characteristic, status); getCallbackToUse().onCharacteristicRead(gatt, characteristic, status);
} }
checkWaitingCharacteristic(characteristic, status); checkWaitingCharacteristic(characteristic, status);
} }
@ -334,8 +357,8 @@ public final class BtLEQueue {
if (!checkCorrectGattInstance(gatt, "descriptor read")) { if (!checkCorrectGattInstance(gatt, "descriptor read")) {
return; return;
} }
if (mExternalGattCallback != null) { if (getCallbackToUse() != null) {
mExternalGattCallback.onDescriptorRead(gatt, descriptor, status); getCallbackToUse().onDescriptorRead(gatt, descriptor, status);
} }
checkWaitingCharacteristic(descriptor.getCharacteristic(), status); checkWaitingCharacteristic(descriptor.getCharacteristic(), status);
} }
@ -346,8 +369,8 @@ public final class BtLEQueue {
if (!checkCorrectGattInstance(gatt, "descriptor write")) { if (!checkCorrectGattInstance(gatt, "descriptor write")) {
return; return;
} }
if (mExternalGattCallback != null) { if (getCallbackToUse() != null) {
mExternalGattCallback.onDescriptorWrite(gatt, descriptor, status); getCallbackToUse().onDescriptorWrite(gatt, descriptor, status);
} }
checkWaitingCharacteristic(descriptor.getCharacteristic(), status); checkWaitingCharacteristic(descriptor.getCharacteristic(), status);
} }
@ -363,8 +386,8 @@ public final class BtLEQueue {
LOG.info("Ignoring characteristic change event from wrong BluetoothGatt instance"); LOG.info("Ignoring characteristic change event from wrong BluetoothGatt instance");
return; return;
} }
if (mExternalGattCallback != null) { if (getCallbackToUse() != null) {
mExternalGattCallback.onCharacteristicChanged(gatt, characteristic); getCallbackToUse().onCharacteristicChanged(gatt, characteristic);
} }
} }
@ -378,8 +401,8 @@ public final class BtLEQueue {
LOG.info("Ignoring remote rssi event from wrong BluetoothGatt instance"); LOG.info("Ignoring remote rssi event from wrong BluetoothGatt instance");
return; return;
} }
if (mExternalGattCallback != null) { if (getCallbackToUse() != null) {
mExternalGattCallback.onReadRemoteRssi(gatt, rssi, status); getCallbackToUse().onReadRemoteRssi(gatt, rssi, status);
} }
} }
@ -398,9 +421,13 @@ public final class BtLEQueue {
} }
} }
} }
};
private String getStatusString(int status) { private String getStatusString(int status) {
return status == BluetoothGatt.GATT_SUCCESS ? " (success)" : " (failed: " + status + ")"; return status == BluetoothGatt.GATT_SUCCESS ? " (success)" : " (failed: " + status + ")";
} }
public void reset() {
mTransactionGattCallback = null;
}
};
} }

View File

@ -1,5 +1,7 @@
package nodomain.freeyourgadget.gadgetbridge.service.btle; package nodomain.freeyourgadget.gadgetbridge.service.btle;
import android.support.annotation.Nullable;
import java.text.DateFormat; import java.text.DateFormat;
import java.util.ArrayList; import java.util.ArrayList;
import java.util.Collections; import java.util.Collections;
@ -17,6 +19,7 @@ public class Transaction {
private String mName; private String mName;
private List<BtLEAction> mActions = new ArrayList<>(4); private List<BtLEAction> mActions = new ArrayList<>(4);
private long creationTimestamp = System.currentTimeMillis(); private long creationTimestamp = System.currentTimeMillis();
private @Nullable GattCallback gattCallback;
public Transaction(String taskName) { public Transaction(String taskName) {
this.mName = taskName; this.mName = taskName;
@ -46,4 +49,15 @@ public class Transaction {
public String toString() { public String toString() {
return String.format(Locale.US, "%s: Transaction task: %s with %d actions", getCreationTime(), getTaskName(), mActions.size()); return String.format(Locale.US, "%s: Transaction task: %s with %d actions", getCreationTime(), getTaskName(), mActions.size());
} }
public void setGattCallback(@Nullable GattCallback callback) {
gattCallback = callback;
}
/**
* Returns the GattCallback for this transaction, or null if none.
*/
public @Nullable GattCallback getGattCallback() {
return gattCallback;
}
} }

View File

@ -1,6 +1,7 @@
package nodomain.freeyourgadget.gadgetbridge.service.btle; package nodomain.freeyourgadget.gadgetbridge.service.btle;
import android.bluetooth.BluetoothGattCharacteristic; import android.bluetooth.BluetoothGattCharacteristic;
import android.support.annotation.Nullable;
import org.slf4j.Logger; import org.slf4j.Logger;
import org.slf4j.LoggerFactory; import org.slf4j.LoggerFactory;
@ -60,6 +61,19 @@ public class TransactionBuilder {
return this; return this;
} }
/**
* Sets a GattCallback instance that will be called when the transaction is executed,
* resulting in GattCallback events.
* @param callback the callback to set, may be null
*/
public void setGattCallback(@Nullable GattCallback callback) {
mTransaction.setGattCallback(callback);
}
public @Nullable GattCallback getGattCallback() {
return mTransaction.getGattCallback();
}
/** /**
* To be used as the final step to execute the transaction by the given queue. * To be used as the final step to execute the transaction by the given queue.
* *