Create the wait-latch before running the action, and only if neeeded

Otherwise the result handler might be called before the wait-latch
has been created, leading to a deadlock of the thread.

Also: only wait for read- and write actions, but not for wait-actions.
This commit is contained in:
cpfeiffer 2015-05-17 21:55:02 +02:00
parent 55400817b4
commit 9819819b92
5 changed files with 45 additions and 6 deletions

View File

@ -22,6 +22,20 @@ public abstract class BtLEAction {
this.characteristic = characteristic; this.characteristic = characteristic;
} }
/**
* Returns true if this actions expects an (async) result which must
* be waited for, before continuing with other actions.
*
* This is needed because the current Bluedroid stack can only deal
* with one single bluetooth operation at a time.
*/
public abstract boolean expectsResult();
/**
* Executes this action, e.g. reads or write a GATT characteristic.
* @param gatt the characteristic to manipulate, or null if none.
* @return true if the action was successful, false otherwise
*/
public abstract boolean run(BluetoothGatt gatt); public abstract boolean run(BluetoothGatt gatt);
/** /**

View File

@ -42,7 +42,7 @@ public final class BtLEQueue {
private BluetoothGattCharacteristic mWaitCharacteristic; private BluetoothGattCharacteristic mWaitCharacteristic;
private GattCallback mExternalGattCallback; private GattCallback mExternalGattCallback;
private Thread dispatchThread = new Thread("Bluetooth GATT Dispatcher") { private Thread dispatchThread = new Thread("GadgetBridge GATT Dispatcher") {
@Override @Override
public void run() { public void run() {
@ -68,13 +68,18 @@ public final class BtLEQueue {
// 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()) {
mWaitCharacteristic = action.getCharacteristic(); mWaitCharacteristic = action.getCharacteristic();
if (action.run(mBluetoothGatt)) { boolean waitForResult = action.expectsResult();
if (waitForResult) {
mWaitForActionResultLatch = new CountDownLatch(1); mWaitForActionResultLatch = new CountDownLatch(1);
}
if (action.run(mBluetoothGatt)) {
if (waitForResult) {
mWaitForActionResultLatch.await(); mWaitForActionResultLatch.await();
mWaitForActionResultLatch = null; mWaitForActionResultLatch = null;
if (mAbortTransaction) { if (mAbortTransaction) {
break; break;
} }
}
} else { } else {
LOG.error("Action returned false: " + action); LOG.error("Action returned false: " + action);
break; // abort the transaction break; // abort the transaction
@ -286,6 +291,10 @@ public final class BtLEQueue {
if (mWaitForActionResultLatch != null) { if (mWaitForActionResultLatch != null) {
mWaitForActionResultLatch.countDown(); mWaitForActionResultLatch.countDown();
} }
} else {
if (BtLEQueue.this.mWaitCharacteristic != null) {
LOG.error("checkWaitingCharacteristic: mismatched characteristic received: " + characteristic != null ? characteristic.getUuid().toString() : "(null)");
}
} }
} }
}; };

View File

@ -19,4 +19,9 @@ public class ReadAction extends BtLEAction {
public boolean run(BluetoothGatt gatt) { public boolean run(BluetoothGatt gatt) {
return gatt.readCharacteristic(getCharacteristic()); return gatt.readCharacteristic(getCharacteristic());
} }
@Override
public boolean expectsResult() {
return true;
}
} }

View File

@ -19,4 +19,10 @@ public class WaitAction extends BtLEAction {
return false; return false;
} }
} }
@Override
public boolean expectsResult() {
// no BT communication at all, no result
return false;
}
} }

View File

@ -25,4 +25,9 @@ public class WriteAction extends BtLEAction {
} }
return false; return false;
} }
@Override
public boolean expectsResult() {
return true;
}
} }