diff options
author | Sven Gothel <[email protected]> | 2020-06-09 18:52:31 +0200 |
---|---|---|
committer | Sven Gothel <[email protected]> | 2020-06-09 18:52:31 +0200 |
commit | 74d71479facbb4fc6eda6a2dbf9cb2ad23f99223 (patch) | |
tree | 1002500334470dee2e6b8b0062457f4a06ce8b9a /java/direct_bt | |
parent | 2048b75e91eaa037821c1340dd3b604d1af6b35a (diff) |
DBT Adapter/Device (java): Use AtomicBoolean for states and only handle results from AdapterStatusListener
- DBTAdapter.java: Explicitly lock user callbacks (like DBTDevice)
- Remove unnecessary synchronized from methods, AtomicBoolean and explicit locks must suffice
Diffstat (limited to 'java/direct_bt')
-rw-r--r-- | java/direct_bt/tinyb/DBTAdapter.java | 142 | ||||
-rw-r--r-- | java/direct_bt/tinyb/DBTDevice.java | 150 |
2 files changed, 139 insertions, 153 deletions
diff --git a/java/direct_bt/tinyb/DBTAdapter.java b/java/direct_bt/tinyb/DBTAdapter.java index 386dc0e2..4f0d1025 100644 --- a/java/direct_bt/tinyb/DBTAdapter.java +++ b/java/direct_bt/tinyb/DBTAdapter.java @@ -30,6 +30,7 @@ import java.util.Collections; import java.util.Iterator; import java.util.List; import java.util.UUID; +import java.util.concurrent.atomic.AtomicBoolean; import java.util.concurrent.atomic.AtomicInteger; import org.tinyb.AdapterSettings; @@ -56,18 +57,18 @@ public class DBTAdapter extends DBTObject implements BluetoothAdapter private final String address; private final String name; - private final Object stateLock = new Object(); private final Object discoveredDevicesLock = new Object(); + private final Object userCallbackLock = new Object(); - private BluetoothNotification<Boolean> discoverableNotification = null; - private volatile boolean isDiscoverable = false; - private BluetoothNotification<Boolean> discoveringNotification = null; - private volatile boolean isDiscovering = false; + private BluetoothNotification<Boolean> userDiscoverableNotificationCB = null; + private final AtomicBoolean isDiscoverable = new AtomicBoolean(false); + private BluetoothNotification<Boolean> userDiscoveringNotificationCB = null; + private final AtomicBoolean isDiscovering = new AtomicBoolean(false); - private BluetoothNotification<Boolean> poweredNotification = null; - private volatile boolean isPowered = false; - private BluetoothNotification<Boolean> pairableNotification = null; - private volatile boolean isPairable = false; + private BluetoothNotification<Boolean> userPoweredNotificationCB = null; + private final AtomicBoolean isPowered = new AtomicBoolean(false); + private BluetoothNotification<Boolean> userPairableNotificationCB = null; + private final AtomicBoolean isPairable = new AtomicBoolean(false); private final List<BluetoothDevice> discoveredDevices = new ArrayList<BluetoothDevice>(); @@ -196,55 +197,73 @@ public class DBTAdapter extends DBTObject implements BluetoothAdapter /* Java callbacks */ @Override - public boolean getPowered() { return isPowered; } + public boolean getPowered() { return isPowered.get(); } @Override - public synchronized void enablePoweredNotifications(final BluetoothNotification<Boolean> callback) { - poweredNotification = callback; + public void enablePoweredNotifications(final BluetoothNotification<Boolean> callback) { + synchronized(userCallbackLock) { + userPoweredNotificationCB = callback; + } } @Override - public synchronized void disablePoweredNotifications() { - poweredNotification = null; + public void disablePoweredNotifications() { + synchronized(userCallbackLock) { + userPoweredNotificationCB = null; + } } @Override - public boolean getDiscoverable() { return isDiscoverable; } + public boolean getDiscoverable() { return isDiscoverable.get(); } @Override - public synchronized void enableDiscoverableNotifications(final BluetoothNotification<Boolean> callback) { - discoverableNotification = callback; + public void enableDiscoverableNotifications(final BluetoothNotification<Boolean> callback) { + synchronized(userCallbackLock) { + userDiscoverableNotificationCB = callback; + } } @Override - public synchronized void disableDiscoverableNotifications() { - discoverableNotification = null; + public void disableDiscoverableNotifications() { + synchronized(userCallbackLock) { + userDiscoverableNotificationCB = null; + } } @Override - public boolean getDiscovering() { return isDiscovering; } + public boolean getDiscovering() { + return isDiscovering.get(); + } @Override - public synchronized void enableDiscoveringNotifications(final BluetoothNotification<Boolean> callback) { - discoveringNotification = callback; + public void enableDiscoveringNotifications(final BluetoothNotification<Boolean> callback) { + synchronized(userCallbackLock) { + userDiscoveringNotificationCB = callback; + } } @Override - public synchronized void disableDiscoveringNotifications() { - discoveringNotification = null; + public void disableDiscoveringNotifications() { + synchronized(userCallbackLock) { + userDiscoveringNotificationCB = null; + } } @Override - public boolean getPairable() { return isPairable; } + public boolean getPairable() { return isPairable.get(); } @Override - public synchronized void enablePairableNotifications(final BluetoothNotification<Boolean> callback) { - pairableNotification = callback; + public void enablePairableNotifications(final BluetoothNotification<Boolean> callback) { + synchronized(userCallbackLock) { + userPairableNotificationCB = callback; + } } @Override - public synchronized void disablePairableNotifications() { - pairableNotification = null; + public void disablePairableNotifications() { + synchronized(userCallbackLock) { + userPairableNotificationCB = null; + } } @Override @@ -287,19 +306,19 @@ public class DBTAdapter extends DBTObject implements BluetoothAdapter } @Override - public synchronized boolean startDiscovery(final boolean keepAlive) throws BluetoothException { - removeDevices(); - final boolean res = startDiscoveryImpl(keepAlive); - isDiscovering = res; - return res; + public boolean startDiscovery(final boolean keepAlive) throws BluetoothException { + if( !isDiscovering.get() ) { + removeDevices(); + return startDiscoveryImpl(keepAlive); // event callbacks will be generated by implementation + } + return true; } private native boolean startDiscoveryImpl(boolean keepAlive) throws BluetoothException; @Override - public synchronized boolean stopDiscovery() throws BluetoothException { - if( isDiscovering ) { - isDiscovering = false; - return stopDiscoveryImpl(); + public boolean stopDiscovery() throws BluetoothException { + if( isDiscovering.get() ) { + return stopDiscoveryImpl(); // event callbacks will be generated by implementation } return false; } @@ -319,7 +338,9 @@ public class DBTAdapter extends DBTObject implements BluetoothAdapter final int cj = removeDiscoveredDevices(); final int cn = removeDevicesImpl(); if( cj != cn ) { - System.err.println("DBTAdapter::removeDevices: Inconsistent discovered device count: Native "+cn+", callback "+cj); + if( DEBUG ) { + System.err.println("DBTAdapter::removeDevices: Inconsistent discovered device count: Native "+cn+", callback "+cj); + } } return cn; } @@ -368,28 +389,37 @@ public class DBTAdapter extends DBTObject implements BluetoothAdapter } { if( changedmask.isSet(AdapterSettings.SettingType.POWERED) ) { - isPowered = newmask.isSet(AdapterSettings.SettingType.POWERED); - final BluetoothNotification<Boolean> _poweredNotification = poweredNotification; - if( null != _poweredNotification ) { - _poweredNotification.run(isPowered); + final boolean _isPowered = newmask.isSet(AdapterSettings.SettingType.POWERED); + if( isPowered.compareAndSet(!_isPowered, _isPowered) ) { + synchronized(userCallbackLock) { + if( null != userPoweredNotificationCB ) { + userPoweredNotificationCB.run(_isPowered); + } + } } } } { if( changedmask.isSet(AdapterSettings.SettingType.DISCOVERABLE) ) { - isDiscoverable = newmask.isSet(AdapterSettings.SettingType.DISCOVERABLE); - final BluetoothNotification<Boolean> _discoverableNotification = discoverableNotification; - if( null != _discoverableNotification ) { - _discoverableNotification.run( isDiscoverable ); + final boolean _isDiscoverable = newmask.isSet(AdapterSettings.SettingType.DISCOVERABLE); + if( isDiscoverable.compareAndSet(!_isDiscoverable, _isDiscoverable) ) { + synchronized(userCallbackLock) { + if( null != userDiscoverableNotificationCB ) { + userDiscoverableNotificationCB.run( _isDiscoverable ); + } + } } } } { if( changedmask.isSet(AdapterSettings.SettingType.BONDABLE) ) { - isPairable = newmask.isSet(AdapterSettings.SettingType.BONDABLE); - final BluetoothNotification<Boolean> _pairableNotification = pairableNotification; - if( null != _pairableNotification ) { - _pairableNotification.run( isPairable ); + final boolean _isPairable = newmask.isSet(AdapterSettings.SettingType.BONDABLE); + if( isPairable.compareAndSet(!_isPairable, _isPairable) ) { + synchronized(userCallbackLock) { + if( null != userPairableNotificationCB ) { + userPairableNotificationCB.run( _isPairable ); + } + } } } } @@ -399,13 +429,13 @@ public class DBTAdapter extends DBTObject implements BluetoothAdapter if( DEBUG ) { System.err.println("Adapter.StatusListener.DISCOVERING: enabled "+enabled+", keepAlive "+keepAlive+" on "+adapter); } - if( isDiscovering != enabled ) { - isDiscovering = enabled; - if( null != discoveringNotification ) { - discoveringNotification.run(enabled); + if( isDiscovering.compareAndSet(!enabled, enabled) ) { + synchronized(userCallbackLock) { + if( null != userDiscoveringNotificationCB ) { + userDiscoveringNotificationCB.run(enabled); + } } } - } @Override public void deviceFound(final BluetoothDevice device, final long timestamp) { diff --git a/java/direct_bt/tinyb/DBTDevice.java b/java/direct_bt/tinyb/DBTDevice.java index 53f17859..2fc66bf9 100644 --- a/java/direct_bt/tinyb/DBTDevice.java +++ b/java/direct_bt/tinyb/DBTDevice.java @@ -27,6 +27,7 @@ package direct_bt.tinyb; import java.util.List; import java.util.Map; +import java.util.concurrent.atomic.AtomicBoolean; import org.tinyb.AdapterStatusListener; import org.tinyb.BluetoothAddressType; @@ -56,47 +57,49 @@ public class DBTDevice extends DBTObject implements BluetoothDevice private final long blockedNotificationRef = 0; private BluetoothNotification<Boolean> userBlockedNotificationsCB = null; - private boolean isBlocked = false; + private final AtomicBoolean isBlocked = new AtomicBoolean(false); private final long pairedNotificationRef = 0; private BluetoothNotification<Boolean> userPairedNotificationsCB = null; - private boolean isPaired = false; + private final AtomicBoolean isPaired = new AtomicBoolean(false); private final long trustedNotificationRef = 0; private BluetoothNotification<Boolean> userTrustedNotificationsCB = null; - private boolean isTrusted = false; + private final AtomicBoolean isTrusted = new AtomicBoolean(false); private BluetoothNotification<Boolean> userConnectedNotificationsCB = null; - private boolean isConnected = false; + private final AtomicBoolean isConnected = new AtomicBoolean(false); private BluetoothNotification<Short> userRSSINotificationsCB = null; private BluetoothNotification<Map<Short, byte[]> > userManufDataNotificationsCB = null; private BluetoothNotification<Boolean> userServicesResolvedNotificationsCB = null; - private boolean servicesResolved = false; + private final AtomicBoolean servicesResolved = new AtomicBoolean(false); private short appearance = 0; final AdapterStatusListener statusListener = new AdapterStatusListener() { @Override public void deviceUpdated(final BluetoothDevice device, final EIRDataTypeSet updateMask, final long timestamp) { - synchronized(userCallbackLock) { - if( updateMask.isSet( EIRDataTypeSet.DataType.RSSI ) && null != userRSSINotificationsCB ) { - userRSSINotificationsCB.run(getRSSI()); - } - if( updateMask.isSet( EIRDataTypeSet.DataType.MANUF_DATA ) && null != userManufDataNotificationsCB ) { - userManufDataNotificationsCB.run(getManufacturerData()); + final boolean rssiUpdated = updateMask.isSet( EIRDataTypeSet.DataType.RSSI ); + final boolean mdUpdated = updateMask.isSet( EIRDataTypeSet.DataType.MANUF_DATA ) + if( rssiUpdated || mdUpdated ) { + synchronized(userCallbackLock) { + if( rssiUpdated && null != userRSSINotificationsCB ) { + userRSSINotificationsCB.run(getRSSI()); + } + if( mdUpdated && null != userManufDataNotificationsCB ) { + userManufDataNotificationsCB.run(getManufacturerData()); + } } } } @Override public void deviceConnected(final BluetoothDevice device, final long timestamp) { - if( !isConnected ) { - isConnected = true; + if( isConnected.compareAndSet(false, true) ) { synchronized(userCallbackLock) { if( null != userConnectedNotificationsCB ) { userConnectedNotificationsCB.run(Boolean.TRUE); } - if( !servicesResolved ) { - servicesResolved = true; + if( servicesResolved.compareAndSet(false, true) ) { if( null != userServicesResolvedNotificationsCB ) { userServicesResolvedNotificationsCB.run(Boolean.TRUE); } @@ -106,11 +109,9 @@ public class DBTDevice extends DBTObject implements BluetoothDevice } @Override public void deviceDisconnected(final BluetoothDevice device, final HCIStatusCode reason, final long timestamp) { - if( isConnected ) { - isConnected = false; + if( isConnected.compareAndSet(true, false) ) { synchronized(userCallbackLock) { - if( servicesResolved ) { - servicesResolved = false; + if( servicesResolved.compareAndSet(true, false) ) { if( null != userServicesResolvedNotificationsCB ) { userServicesResolvedNotificationsCB.run(Boolean.FALSE); } @@ -129,10 +130,12 @@ public class DBTDevice extends DBTObject implements BluetoothDevice if( DEBUG ) { System.err.println("Device.BlockedNotification: "+isBlocked+" -> "+value+" on "+DBTDevice.this.toString()); } - isBlocked = value.booleanValue(); - synchronized(userCallbackLock) { - if( null != userBlockedNotificationsCB ) { - userBlockedNotificationsCB.run(value); + final boolean _isBlocked = value.booleanValue(); + if( isBlocked.compareAndSet(!_isBlocked, _isBlocked) ) { + synchronized(userCallbackLock) { + if( null != userBlockedNotificationsCB ) { + userBlockedNotificationsCB.run(value); + } } } } @@ -144,10 +147,12 @@ public class DBTDevice extends DBTObject implements BluetoothDevice if( DEBUG ) { System.err.println("Device.PairedNotification: "+isPaired+" -> "+value+" on "+DBTDevice.this.toString()); } - isPaired = value.booleanValue(); - synchronized(userCallbackLock) { - if( null != userPairedNotificationsCB ) { - userPairedNotificationsCB.run(value); + final boolean _isPaired = value.booleanValue(); + if( isPaired.compareAndSet(!_isPaired, _isPaired) ) { + synchronized(userCallbackLock) { + if( null != userPairedNotificationsCB ) { + userPairedNotificationsCB.run(value); + } } } } @@ -159,10 +164,12 @@ public class DBTDevice extends DBTObject implements BluetoothDevice if( DEBUG ) { System.err.println("Device.TrustedNotification: "+isTrusted+" -> "+value+" on "+DBTDevice.this.toString()); } - isTrusted = value.booleanValue(); - synchronized(userCallbackLock) { - if( null != userTrustedNotificationsCB ) { - userTrustedNotificationsCB.run(value); + final boolean _isTrusted = value.booleanValue(); + if( isTrusted.compareAndSet(!_isTrusted, _isTrusted) ) { + synchronized(userCallbackLock) { + if( null != userTrustedNotificationsCB ) { + userTrustedNotificationsCB.run(value); + } } } } @@ -295,55 +302,23 @@ public class DBTDevice extends DBTObject implements BluetoothDevice } @Override - public final boolean getConnected() { return isConnected; } + public final boolean getConnected() { return isConnected.get(); } @Override public final boolean disconnect() throws BluetoothException { - boolean res = false; - if( isConnected ) { - res = disconnectImpl(); - if( res ) { - // FIXME: Split up - may offload to other thread - // Currently service resolution performed in connectImpl()! - synchronized(userCallbackLock) { - servicesResolved = false; - if( null != userServicesResolvedNotificationsCB ) { - userServicesResolvedNotificationsCB.run(Boolean.FALSE); - } - - isConnected = false; - if( null != userConnectedNotificationsCB ) { - userConnectedNotificationsCB.run(Boolean.FALSE); - } - } - } + if( isConnected.get() ) { + return disconnectImpl(); // event callbacks will be generated by implementation } - return res; + return false; } private native boolean disconnectImpl() throws BluetoothException; @Override public final boolean connect() throws BluetoothException { - boolean res = false; - if( !isConnected ) { - res = connectImpl(); - if( res ) { - synchronized(userCallbackLock) { - isConnected = true; - if( null != userConnectedNotificationsCB ) { - userConnectedNotificationsCB.run(Boolean.TRUE); - } - - // FIXME: Split up - may offload to other thread - // Currently service resolution performed in connectImpl()! - servicesResolved = true; - if( null != userServicesResolvedNotificationsCB ) { - userServicesResolvedNotificationsCB.run(Boolean.TRUE); - } - } - } + if( !isConnected.get() ) { + return connectImpl(); // event callbacks will be generated by implementation } - return res; + return false; } private native boolean connectImpl() throws BluetoothException; @@ -351,26 +326,11 @@ public class DBTDevice extends DBTObject implements BluetoothDevice public boolean connect(final short le_scan_interval, final short le_scan_window, final short conn_interval_min, final short conn_interval_max, final short conn_latency, final short timeout) { - boolean res = false; - if( !isConnected ) { - res = connectImpl(le_scan_interval, le_scan_window, conn_interval_min, conn_interval_max, conn_latency, timeout); - if( res ) { - synchronized(userCallbackLock) { - isConnected = true; - if( null != userConnectedNotificationsCB ) { - userConnectedNotificationsCB.run(Boolean.TRUE); - } - - // FIXME: Split up - may offload to other thread - // Currently service resolution performed in connectImpl()! - servicesResolved = true; - if( null != userServicesResolvedNotificationsCB ) { - userServicesResolvedNotificationsCB.run(Boolean.TRUE); - } - } - } + if( !isConnected.get() ) { + // event callbacks will be generated by implementation + return connectImpl(le_scan_interval, le_scan_window, conn_interval_min, conn_interval_max, conn_latency, timeout); } - return res; + return false; } private native boolean connectImpl(final short le_scan_interval, final short le_scan_window, final short conn_interval_min, final short conn_interval_max, @@ -423,7 +383,7 @@ public class DBTDevice extends DBTObject implements BluetoothDevice } @Override - public boolean getServicesResolved () { return servicesResolved; } + public boolean getServicesResolved () { return servicesResolved.get(); } @Override public short getAppearance() { return appearance; } @@ -441,9 +401,7 @@ public class DBTDevice extends DBTObject implements BluetoothDevice } } @Override - public boolean getBlocked() { - return isBlocked; - } + public boolean getBlocked() { return isBlocked.get(); } @Override public void setBlocked(final boolean value) { @@ -480,7 +438,7 @@ public class DBTDevice extends DBTObject implements BluetoothDevice } @Override - public boolean getPaired() { return isPaired; } + public boolean getPaired() { return isPaired.get(); } @Override public void enableTrustedNotifications(final BluetoothNotification<Boolean> callback) { @@ -497,9 +455,7 @@ public class DBTDevice extends DBTObject implements BluetoothDevice } @Override - public boolean getTrusted() { - return isTrusted; - } + public boolean getTrusted() { return isTrusted.get(); } @Override public void setTrusted(final boolean value) { |