From 628259779081c20bcf8388397f0ee3a03faac74a Mon Sep 17 00:00:00 2001 From: cpfeiffer Date: Thu, 9 Mar 2017 22:46:08 +0100 Subject: [PATCH] Handle BT issues with discovered characteristics It occurred to me that onServicesDiscovered() was called multiple times whenever I connected to my Mi Band 2. Either the band actually sent the characteristics in multiple chunks or Android itself notified multiple times. So we gracefully handle this by - updating the list of characteristics - *not* initializing the device again when it *is* already initialized or at least initializing. --- .../btle/AbstractBTLEDeviceSupport.java | 27 ++++++++++++++----- 1 file changed, 21 insertions(+), 6 deletions(-) diff --git a/app/src/main/java/nodomain/freeyourgadget/gadgetbridge/service/btle/AbstractBTLEDeviceSupport.java b/app/src/main/java/nodomain/freeyourgadget/gadgetbridge/service/btle/AbstractBTLEDeviceSupport.java index e87c50e3..48e5c3e6 100644 --- a/app/src/main/java/nodomain/freeyourgadget/gadgetbridge/service/btle/AbstractBTLEDeviceSupport.java +++ b/app/src/main/java/nodomain/freeyourgadget/gadgetbridge/service/btle/AbstractBTLEDeviceSupport.java @@ -12,10 +12,13 @@ import java.util.ArrayList; import java.util.HashMap; import java.util.HashSet; import java.util.List; +import java.util.Map; +import java.util.Objects; import java.util.Set; import java.util.UUID; import nodomain.freeyourgadget.gadgetbridge.Logging; +import nodomain.freeyourgadget.gadgetbridge.impl.GBDevice; import nodomain.freeyourgadget.gadgetbridge.service.AbstractDeviceSupport; import nodomain.freeyourgadget.gadgetbridge.service.btle.actions.CheckInitializedAction; import nodomain.freeyourgadget.gadgetbridge.service.btle.profiles.AbstractBleProfile; @@ -33,12 +36,13 @@ import nodomain.freeyourgadget.gadgetbridge.service.btle.profiles.AbstractBlePro */ public abstract class AbstractBTLEDeviceSupport extends AbstractDeviceSupport implements GattCallback { private BtLEQueue mQueue; - private HashMap mAvailableCharacteristics; + private Map mAvailableCharacteristics; private final Set mSupportedServices = new HashSet<>(4); private Logger logger; private final List> mSupportedProfiles = new ArrayList<>(); public static final String BASE_UUID = "0000%s-0000-1000-8000-00805f9b34fb"; //this is common for all BTLE devices. see http://stackoverflow.com/questions/18699251/finding-out-android-bluetooth-le-gatt-profiles + private final Object characteristicsMonitor = new Object(); public AbstractBTLEDeviceSupport(Logger logger) { this.logger = logger; @@ -166,10 +170,12 @@ public abstract class AbstractBTLEDeviceSupport extends AbstractDeviceSupport im * @see #addSupportedService(UUID) */ public BluetoothGattCharacteristic getCharacteristic(UUID uuid) { - if (mAvailableCharacteristics == null) { - return null; + synchronized (characteristicsMonitor) { + if (mAvailableCharacteristics == null) { + return null; + } + return mAvailableCharacteristics.get(uuid); } - return mAvailableCharacteristics.get(uuid); } private void gattServicesDiscovered(List discoveredGattServices) { @@ -178,7 +184,7 @@ public abstract class AbstractBTLEDeviceSupport extends AbstractDeviceSupport im return; } Set supportedServices = getSupportedServices(); - mAvailableCharacteristics = new HashMap<>(); + Map newCharacteristics = new HashMap<>(); for (BluetoothGattService service : discoveredGattServices) { if (supportedServices.contains(service.getUuid())) { logger.debug("discovered supported service: " + BleNamesResolver.resolveServiceName(service.getUuid().toString()) + ": " + service.getUuid()); @@ -192,7 +198,11 @@ public abstract class AbstractBTLEDeviceSupport extends AbstractDeviceSupport im intmAvailableCharacteristics.put(characteristic.getUuid(), characteristic); logger.info(" characteristic: " + BleNamesResolver.resolveCharacteristicName(characteristic.getUuid().toString()) + ": " + characteristic.getUuid()); } - mAvailableCharacteristics.putAll(intmAvailableCharacteristics); + newCharacteristics.putAll(intmAvailableCharacteristics); + + synchronized (characteristicsMonitor) { + mAvailableCharacteristics = newCharacteristics; + } } else { logger.debug("discovered unsupported service: " + BleNamesResolver.resolveServiceName(service.getUuid().toString()) + ": " + service.getUuid()); } @@ -224,6 +234,11 @@ public abstract class AbstractBTLEDeviceSupport extends AbstractDeviceSupport im @Override public void onServicesDiscovered(BluetoothGatt gatt) { gattServicesDiscovered(gatt.getServices()); + + if (getDevice().getState().compareTo(GBDevice.State.INITIALIZING) >= 0) { + logger.warn("Services discovered, but device state is already " + getDevice().getState() + " for device: " + getDevice() + ", so ignoring"); + return; + } initializeDevice(createTransactionBuilder("Initializing device")).queue(getQueue()); }