From 9819819b9218304bb20a8dcebc67842dc311e80a Mon Sep 17 00:00:00 2001 From: cpfeiffer Date: Sun, 17 May 2015 21:55:02 +0200 Subject: [PATCH] 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. --- .../gadgetbridge/btle/BtLEAction.java | 14 +++++++++++++ .../gadgetbridge/btle/BtLEQueue.java | 21 +++++++++++++------ .../gadgetbridge/btle/ReadAction.java | 5 +++++ .../gadgetbridge/btle/WaitAction.java | 6 ++++++ .../gadgetbridge/btle/WriteAction.java | 5 +++++ 5 files changed, 45 insertions(+), 6 deletions(-) diff --git a/app/src/main/java/nodomain/freeyourgadget/gadgetbridge/btle/BtLEAction.java b/app/src/main/java/nodomain/freeyourgadget/gadgetbridge/btle/BtLEAction.java index 15508eea3..d29de9448 100644 --- a/app/src/main/java/nodomain/freeyourgadget/gadgetbridge/btle/BtLEAction.java +++ b/app/src/main/java/nodomain/freeyourgadget/gadgetbridge/btle/BtLEAction.java @@ -22,6 +22,20 @@ public abstract class BtLEAction { 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); /** diff --git a/app/src/main/java/nodomain/freeyourgadget/gadgetbridge/btle/BtLEQueue.java b/app/src/main/java/nodomain/freeyourgadget/gadgetbridge/btle/BtLEQueue.java index 66f344104..544ea28e8 100644 --- a/app/src/main/java/nodomain/freeyourgadget/gadgetbridge/btle/BtLEQueue.java +++ b/app/src/main/java/nodomain/freeyourgadget/gadgetbridge/btle/BtLEQueue.java @@ -42,7 +42,7 @@ public final class BtLEQueue { private BluetoothGattCharacteristic mWaitCharacteristic; private GattCallback mExternalGattCallback; - private Thread dispatchThread = new Thread("Bluetooth GATT Dispatcher") { + private Thread dispatchThread = new Thread("GadgetBridge GATT Dispatcher") { @Override public void run() { @@ -68,12 +68,17 @@ public final class BtLEQueue { // Run all actions of the transaction until one doesn't succeed for (BtLEAction action : transaction.getActions()) { mWaitCharacteristic = action.getCharacteristic(); - if (action.run(mBluetoothGatt)) { + boolean waitForResult = action.expectsResult(); + if (waitForResult) { mWaitForActionResultLatch = new CountDownLatch(1); - mWaitForActionResultLatch.await(); - mWaitForActionResultLatch = null; - if (mAbortTransaction) { - break; + } + if (action.run(mBluetoothGatt)) { + if (waitForResult) { + mWaitForActionResultLatch.await(); + mWaitForActionResultLatch = null; + if (mAbortTransaction) { + break; + } } } else { LOG.error("Action returned false: " + action); @@ -286,6 +291,10 @@ public final class BtLEQueue { if (mWaitForActionResultLatch != null) { mWaitForActionResultLatch.countDown(); } + } else { + if (BtLEQueue.this.mWaitCharacteristic != null) { + LOG.error("checkWaitingCharacteristic: mismatched characteristic received: " + characteristic != null ? characteristic.getUuid().toString() : "(null)"); + } } } }; diff --git a/app/src/main/java/nodomain/freeyourgadget/gadgetbridge/btle/ReadAction.java b/app/src/main/java/nodomain/freeyourgadget/gadgetbridge/btle/ReadAction.java index e0c545b54..7f2516c91 100644 --- a/app/src/main/java/nodomain/freeyourgadget/gadgetbridge/btle/ReadAction.java +++ b/app/src/main/java/nodomain/freeyourgadget/gadgetbridge/btle/ReadAction.java @@ -19,4 +19,9 @@ public class ReadAction extends BtLEAction { public boolean run(BluetoothGatt gatt) { return gatt.readCharacteristic(getCharacteristic()); } + + @Override + public boolean expectsResult() { + return true; + } } diff --git a/app/src/main/java/nodomain/freeyourgadget/gadgetbridge/btle/WaitAction.java b/app/src/main/java/nodomain/freeyourgadget/gadgetbridge/btle/WaitAction.java index 851f7d5e8..f8e4484de 100644 --- a/app/src/main/java/nodomain/freeyourgadget/gadgetbridge/btle/WaitAction.java +++ b/app/src/main/java/nodomain/freeyourgadget/gadgetbridge/btle/WaitAction.java @@ -19,4 +19,10 @@ public class WaitAction extends BtLEAction { return false; } } + + @Override + public boolean expectsResult() { + // no BT communication at all, no result + return false; + } } diff --git a/app/src/main/java/nodomain/freeyourgadget/gadgetbridge/btle/WriteAction.java b/app/src/main/java/nodomain/freeyourgadget/gadgetbridge/btle/WriteAction.java index b09092766..bf4404d41 100644 --- a/app/src/main/java/nodomain/freeyourgadget/gadgetbridge/btle/WriteAction.java +++ b/app/src/main/java/nodomain/freeyourgadget/gadgetbridge/btle/WriteAction.java @@ -25,4 +25,9 @@ public class WriteAction extends BtLEAction { } return false; } + + @Override + public boolean expectsResult() { + return true; + } }