diff options
Diffstat (limited to 'app/src/main/java/io/trygvis/android/bt/BtActionExecutor.java')
-rw-r--r-- | app/src/main/java/io/trygvis/android/bt/BtActionExecutor.java | 358 |
1 files changed, 174 insertions, 184 deletions
diff --git a/app/src/main/java/io/trygvis/android/bt/BtActionExecutor.java b/app/src/main/java/io/trygvis/android/bt/BtActionExecutor.java index 8cbf87c..984c738 100644 --- a/app/src/main/java/io/trygvis/android/bt/BtActionExecutor.java +++ b/app/src/main/java/io/trygvis/android/bt/BtActionExecutor.java @@ -12,6 +12,9 @@ import java.util.Iterator; import java.util.List; import java.util.Queue; +import io.trygvis.android.F2; +import io.trygvis.android.Function; + import static io.trygvis.android.bt.BtActionExecutor.EventType.onCharacteristicChanged; import static io.trygvis.android.bt.BtActionExecutor.EventType.onCharacteristicRead; import static io.trygvis.android.bt.BtActionExecutor.EventType.onCharacteristicWrite; @@ -19,239 +22,146 @@ import static io.trygvis.android.bt.BtActionExecutor.EventType.onConnectionState import static io.trygvis.android.bt.BtActionExecutor.EventType.onDescriptorRead; import static io.trygvis.android.bt.BtActionExecutor.EventType.onDescriptorWrite; import static io.trygvis.android.bt.BtActionExecutor.EventType.onFailure; +import static io.trygvis.android.bt.BtActionExecutor.EventType.onFinally; import static io.trygvis.android.bt.BtActionExecutor.EventType.onReliableWriteCompleted; import static io.trygvis.android.bt.BtActionExecutor.EventType.onServicesDiscovered; public class BtActionExecutor { private final static String TAG = BtActionExecutor.class.getSimpleName(); private final Queue<BtCallback> actionQ = new ArrayDeque<>(); + private final Queue<BtCallback> failureQ = new ArrayDeque<>(); private final Queue<BtCallback> finallyQ = new ArrayDeque<>(); - private final List<BluetoothGattCallback> remoteRssi = new ArrayList<>(); - - public BtActionExecutor() { - } - - public BtActionExecutor(BtCallback first) { - actionQ.add(first); - } -// public static final BtCallback waitForIt = new BtCallback("Wait for it") { -// @Override -// public boolean onCharacteristicWrite(BluetoothGatt gatt, BluetoothGattCharacteristic characteristic) { -// Log.w(TAG, "wait for it...!"); -// return true; -// } -// }; - -// public synchronized BtActionExecutor onSuccess(BtCallback btCallback) { -// actionQ.add(btCallback); -// return this; -// } - - public synchronized BtActionExecutor onConnectionStateChange(OnConnectionStateChange callback) { + public synchronized BtActionExecutor onConnectionStateChange(F2<BluetoothGatt, Integer, Boolean> callback) { actionQ.add(new BtCallback("onConnectionStateChange") { @Override public boolean onConnectionStateChange(BluetoothGatt gatt, int newState) { - return callback.onConnectionStateChange(gatt, newState); + return callback.apply(gatt, newState); } }); return this; } - public synchronized BtActionExecutor onServicesDiscovered(OnServicesDiscovered callback) { + public synchronized BtActionExecutor onServicesDiscovered(Function<BluetoothGatt, Boolean> callback) { actionQ.add(new BtCallback("onServicesDiscovered") { @Override public boolean onServicesDiscovered(BluetoothGatt gatt) { - return callback.onServicesDiscovered(gatt); + return callback.apply(gatt); } }); return this; } - public synchronized BtActionExecutor onCharacteristicRead(OnCharacteristicRead callback) { + public synchronized BtActionExecutor onCharacteristicRead(F2<BluetoothGatt, BluetoothGattCharacteristic, Boolean> callback) { actionQ.add(new BtCallback("onCharacteristicRead") { @Override public boolean onCharacteristicRead(BluetoothGatt gatt, BluetoothGattCharacteristic characteristic) { - return callback.onCharacteristicRead(gatt, characteristic); + return callback.apply(gatt, characteristic); } }); return this; } - public synchronized BtActionExecutor onCharacteristicWrite(OnCharacteristicWrite callback) { + public synchronized BtActionExecutor onCharacteristicWrite(F2<BluetoothGatt, BluetoothGattCharacteristic, Boolean> callback) { actionQ.add(new BtCallback("onCharacteristicWrite") { @Override public boolean onCharacteristicWrite(BluetoothGatt gatt, BluetoothGattCharacteristic characteristic) { - return callback.onCharacteristicWrite(gatt, characteristic); + return callback.apply(gatt, characteristic); } }); return this; } - public synchronized BtActionExecutor onCharacteristicChanged(OnCharacteristicChanged callback) { + public synchronized BtActionExecutor onCharacteristicChanged(F2<BluetoothGatt, BluetoothGattCharacteristic, Boolean> callback) { actionQ.add(new BtCallback("onCharacteristicChanged") { @Override public boolean onCharacteristicChanged(BluetoothGatt gatt, BluetoothGattCharacteristic characteristic) { - return callback.onCharacteristicChanged(gatt, characteristic); + return callback.apply(gatt, characteristic); } }); return this; } - public synchronized BtActionExecutor onDescriptorRead(OnDescriptorRead callback) { + public synchronized BtActionExecutor onDescriptorRead(F2<BluetoothGatt, BluetoothGattDescriptor, Boolean> callback) { actionQ.add(new BtCallback("onDescriptorRead") { @Override public boolean onDescriptorRead(BluetoothGatt gatt, BluetoothGattDescriptor descriptor) { - return callback.onDescriptorRead(gatt, descriptor); + return callback.apply(gatt, descriptor); } }); return this; } - public synchronized BtActionExecutor onDescriptorWrite(OnDescriptorWrite callback) { + public synchronized BtActionExecutor onDescriptorWrite(F2<BluetoothGatt, BluetoothGattDescriptor, Boolean> callback) { actionQ.add(new BtCallback("onDescriptorWrite") { @Override public boolean onDescriptorWrite(BluetoothGatt gatt, BluetoothGattDescriptor descriptor) { - return callback.onDescriptorWrite(gatt, descriptor); + return callback.apply(gatt, descriptor); } }); return this; } - public synchronized BtActionExecutor onReliableWriteCompleted(OnReliableWriteCompleted callback) { + public synchronized BtActionExecutor onReliableWriteCompleted(Function<BluetoothGatt, Boolean> callback) { actionQ.add(new BtCallback("onReliableWriteCompleted") { @Override public boolean onReliableWriteCompleted(BluetoothGatt gatt) { - return callback.onReliableWriteCompleted(gatt); + return callback.apply(gatt); } }); return this; } - public synchronized BtActionExecutor onReadRemoteRssi(OnReadRemoteRssi callback) { + public synchronized BtActionExecutor onReadRemoteRssi(F2<BluetoothGatt, Integer, Boolean> callback) { actionQ.add(new BtCallback("onReadRemoteRssi") { @Override public boolean onReadRemoteRssi(BluetoothGatt gatt, int rssi) { - return callback.onReadRemoteRssi(gatt, rssi); + return callback.apply(gatt, rssi); } }); return this; } - public synchronized BtActionExecutor onFailure(OnFailure callback) { - actionQ.add(new BtCallback("onFailure") { + public synchronized BtActionExecutor onFailure(Runnable callback) { + failureQ.add(new BtCallback("onFailure") { @Override public void onFailure() { - callback.onFailure(); + callback.run(); } }); return this; } - public static interface OnConnectionStateChange { - boolean onConnectionStateChange(BluetoothGatt gatt, int newState); - } - - public static interface OnServicesDiscovered { - boolean onServicesDiscovered(BluetoothGatt gatt); - } - - public static interface OnCharacteristicRead { - boolean onCharacteristicRead(BluetoothGatt gatt, BluetoothGattCharacteristic characteristic); - } - - public static interface OnCharacteristicWrite { - boolean onCharacteristicWrite(BluetoothGatt gatt, BluetoothGattCharacteristic characteristic); - } - - public static interface OnCharacteristicChanged { - boolean onCharacteristicChanged(BluetoothGatt gatt, BluetoothGattCharacteristic characteristic); - } - - public static interface OnDescriptorRead { - boolean onDescriptorRead(BluetoothGatt gatt, BluetoothGattDescriptor descriptor); - } - - public static interface OnDescriptorWrite { - boolean onDescriptorWrite(BluetoothGatt gatt, BluetoothGattDescriptor descriptor); - } - - public static interface OnReliableWriteCompleted { - boolean onReliableWriteCompleted(BluetoothGatt gatt); - } - - public static interface OnReadRemoteRssi { - boolean onReadRemoteRssi(BluetoothGatt gatt, int rssi); - } - - public static interface OnFailure { - void onFailure(); - } - - public synchronized BtActionExecutor addFinally(BtCallback btCallback) { - finallyQ.add(btCallback); + public synchronized BtActionExecutor onFinally(Runnable callback) { + finallyQ.add(new BtCallback("finally") { + @Override + public void onFinally() { + callback.run(); + } + }); return this; } -// public synchronized BtActionExecutor onRemoteRssi(BluetoothGattCallback callback) { -// remoteRssi.add(callback); -// return this; -// } - - void onEvent(EventType key, String values, BluetoothGatt gatt, BluetoothGattCharacteristic characteristic, BluetoothGattDescriptor descriptor, int status, int newState) { - if (status != BluetoothGatt.GATT_SUCCESS) { - Log.w(TAG, "Operation failed: " + key + ", " + values); - doFinally(); - return; - } - - Log.i(TAG, "Bt action completed successfully: callback=" + key); - - BtCallback btCallback; - synchronized (this) { - if (actionQ.isEmpty()) { - Log.d(TAG, "All Bluetooth actions are done"); + public String toString() { + StringBuilder s = new StringBuilder("Queue: "); - doFinally(); - return; - } + Iterator<BtCallback> it = actionQ.iterator(); - try { - Thread.sleep(1000); - } catch (InterruptedException e) { - // ignore + int i = 0; + while (it.hasNext()) { + BtCallback c = it.next(); + if (i > 0) { + s.append(", "); } - btCallback = actionQ.remove(); - Log.i(TAG, "Executing bt action: " + btCallback.name); + s.append(c.name); + i++; } - try { - boolean ok = callCallback(key, gatt, characteristic, descriptor, newState, btCallback); - - if (!ok) { - Log.w(TAG, "The callback don't want to continue."); - doFinally(); - } - - if (actionQ.isEmpty()) { - Log.i(TAG, "The queue is empty"); - } - } catch (NotOverriddenException e) { - Log.w(TAG, "Unexpected callback by listener: " + key); - doFinally(); - } + return s.toString(); } - private void doFinally() { - actionQ.clear(); - - for (BtCallback callback = finallyQ.poll(); callback != null; callback = finallyQ.poll()) { - try { - callCallback(onFailure, null, null, null, 0, callback); - } catch (NotOverriddenException e) { - return; - } - } + public BluetoothGattCallback asCallback() { + return new MyBluetoothGattCallback(); } enum EventType { @@ -264,10 +174,13 @@ public class BtActionExecutor { onDescriptorWrite, onReliableWriteCompleted, + onReadRemoteRssi, + onFailure, + onFinally, } - private Boolean callCallback(EventType key, BluetoothGatt gatt, BluetoothGattCharacteristic characteristic, BluetoothGattDescriptor descriptor, int newState, BtCallback btCallback) { + private static Boolean callCallback(EventType key, BluetoothGatt gatt, BluetoothGattCharacteristic characteristic, BluetoothGattDescriptor descriptor, int newState, BtCallback btCallback) { switch (key) { case onConnectionStateChange: return btCallback.onConnectionStateChange(gatt, newState); @@ -289,78 +202,155 @@ public class BtActionExecutor { case onFailure: btCallback.onFailure(); return null; + case onFinally: + btCallback.onFinally(); + return null; default: Log.w(TAG, "Unknown callback: " + key); return null; } } - public String toString() { - StringBuilder s = new StringBuilder("Queue: "); + private class MyBluetoothGattCallback extends BluetoothGattCallback { - Iterator<BtCallback> it = actionQ.iterator(); + private Queue<BtCallback> initialActionQ = new ArrayDeque<>(actionQ); + private List<String> events = new ArrayList<>(); - int i = 0; - while (it.hasNext()) { - BtCallback c = it.next(); - if (i > 0) { - s.append(", "); - } - s.append(c.name); - i++; - } + void onEvent(EventType key, String values, BluetoothGatt gatt, BluetoothGattCharacteristic characteristic, BluetoothGattDescriptor descriptor, int status, int newState) { + boolean success = status == BluetoothGatt.GATT_SUCCESS; + events.add(key + ", " + values + ", success=" + success); - return s.toString(); - } + Log.i(TAG, "Operation failed: " + key + ", " + values + ", success=" + success); - public BluetoothGattCallback asCallback() { - return new BluetoothGattCallback() { - @Override - public void onConnectionStateChange(BluetoothGatt gatt, int status, int newState) { - onEvent(onConnectionStateChange, "status=" + status + ", newState=" + newState, gatt, null, null, status, newState); + if (!success) { + doFailure(); + return; } - @Override - public void onServicesDiscovered(BluetoothGatt gatt, int status) { - onEvent(onServicesDiscovered, "status=" + status, gatt, null, null, status, 9); - } + BtCallback btCallback; + synchronized (this) { + if (actionQ.isEmpty()) { + Log.d(TAG, "All Bluetooth actions are done"); - @Override - public void onCharacteristicRead(BluetoothGatt gatt, BluetoothGattCharacteristic characteristic, int status) { - onEvent(onCharacteristicRead, "status=" + status + ", characteristic=" + characteristic.getUuid(), gatt, characteristic, null, status, 0); - } + doFinally(); + return; + } - @Override - public void onCharacteristicWrite(BluetoothGatt gatt, BluetoothGattCharacteristic characteristic, int status) { - onEvent(onCharacteristicWrite, "status=" + status + ", characteristic=" + characteristic.getUuid(), gatt, characteristic, null, status, 0); + try { + Thread.sleep(1000); + } catch (InterruptedException e) { + // ignore + } + btCallback = actionQ.remove(); + Log.i(TAG, "Executing bt action: " + btCallback.name); } - @Override - public void onCharacteristicChanged(BluetoothGatt gatt, BluetoothGattCharacteristic characteristic) { - onEvent(onCharacteristicChanged, "characteristic=" + characteristic.getUuid(), gatt, characteristic, null, BluetoothGatt.GATT_SUCCESS, 0); + try { + boolean ok = callCallback(key, gatt, characteristic, descriptor, newState, btCallback); + + if (!ok) { + Log.w(TAG, "The callback don't want to continue."); + doFinally(); + } + + if (actionQ.isEmpty()) { + Log.i(TAG, "The queue is empty"); + } + } catch (NotOverriddenException e) { + Log.w(TAG, "Unexpected callback by listener: " + key); + doFailure(); } + } - @Override - public void onDescriptorRead(BluetoothGatt gatt, BluetoothGattDescriptor descriptor, int status) { - onEvent(onDescriptorRead, "status=" + status + ", descriptor=" + descriptor.getUuid(), gatt, null, descriptor, status, 0); + private void doFailure() { + StringBuilder msg = new StringBuilder(); + + msg.append("Expected events: \n"); + for (BtCallback cb : initialActionQ) { + msg.append(" ").append(cb.name).append("\n"); } - @Override - public void onDescriptorWrite(BluetoothGatt gatt, BluetoothGattDescriptor descriptor, int status) { - onEvent(onDescriptorWrite, "status=" + status + ", descriptor=" + descriptor.getUuid(), gatt, null, descriptor, status, 0); + msg.append("Actual events: \n"); + for (String event : events) { + msg.append(" ").append(event).append("\n"); } - @Override - public void onReliableWriteCompleted(BluetoothGatt gatt, int status) { - onEvent(onReliableWriteCompleted, "status=" + status, gatt, null, null, status, 0); + Log.w(TAG, msg.toString()); + + Log.w(TAG, "Executing " + failureQ.size() + " failure handlers"); + + for (BtCallback callback = failureQ.poll(); callback != null; callback = failureQ.poll()) { + try { + callCallback(onFailure, null, null, null, 0, callback); + } catch (NotOverriddenException e) { + return; + } } - @Override - public void onReadRemoteRssi(BluetoothGatt gatt, int rssi, int status) { - for (BluetoothGattCallback callback : remoteRssi) { - callback.onReadRemoteRssi(gatt, rssi, status); + doFinally(); + } + + private void doFinally() { + actionQ.clear(); + + Log.w(TAG, "Executing " + finallyQ.size() + " finally handlers"); + + for (BtCallback callback = finallyQ.poll(); callback != null; callback = finallyQ.poll()) { + try { + callCallback(onFinally, null, null, null, 0, callback); + } catch (NotOverriddenException e) { + return; } } - }; + } + + // ----------------------------------------------------------------------- + // + // ----------------------------------------------------------------------- + + @Override + public void onConnectionStateChange(BluetoothGatt gatt, int status, int newState) { + onEvent(onConnectionStateChange, "status=" + status + ", newState=" + newState, gatt, null, null, status, newState); + } + + @Override + public void onServicesDiscovered(BluetoothGatt gatt, int status) { + onEvent(onServicesDiscovered, "status=" + status, gatt, null, null, status, 9); + } + + @Override + public void onCharacteristicRead(BluetoothGatt gatt, BluetoothGattCharacteristic characteristic, int status) { + onEvent(onCharacteristicRead, "status=" + status + ", characteristic=" + characteristic.getUuid(), gatt, characteristic, null, status, 0); + } + + @Override + public void onCharacteristicWrite(BluetoothGatt gatt, BluetoothGattCharacteristic characteristic, int status) { + onEvent(onCharacteristicWrite, "status=" + status + ", characteristic=" + characteristic.getUuid(), gatt, characteristic, null, status, 0); + } + + @Override + public void onCharacteristicChanged(BluetoothGatt gatt, BluetoothGattCharacteristic characteristic) { + onEvent(onCharacteristicChanged, "characteristic=" + characteristic.getUuid(), gatt, characteristic, null, BluetoothGatt.GATT_SUCCESS, 0); + } + + @Override + public void onDescriptorRead(BluetoothGatt gatt, BluetoothGattDescriptor descriptor, int status) { + onEvent(onDescriptorRead, "status=" + status + ", descriptor=" + descriptor.getUuid(), gatt, null, descriptor, status, 0); + } + + @Override + public void onDescriptorWrite(BluetoothGatt gatt, BluetoothGattDescriptor descriptor, int status) { + onEvent(onDescriptorWrite, "status=" + status + ", descriptor=" + descriptor.getUuid(), gatt, null, descriptor, status, 0); + } + + @Override + public void onReliableWriteCompleted(BluetoothGatt gatt, int status) { + onEvent(onReliableWriteCompleted, "status=" + status, gatt, null, null, status, 0); + } + + @Override + public void onReadRemoteRssi(BluetoothGatt gatt, int rssi, int status) { +// onEvent(onReadRemoteRssi, "status=" + status, gatt, null, null, status, 0); + } } } |