aboutsummaryrefslogtreecommitdiffstats
path: root/java/direct_bt
diff options
context:
space:
mode:
authorSven Gothel <[email protected]>2020-06-09 18:52:31 +0200
committerSven Gothel <[email protected]>2020-06-09 18:52:31 +0200
commit74d71479facbb4fc6eda6a2dbf9cb2ad23f99223 (patch)
tree1002500334470dee2e6b8b0062457f4a06ce8b9a /java/direct_bt
parent2048b75e91eaa037821c1340dd3b604d1af6b35a (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.java142
-rw-r--r--java/direct_bt/tinyb/DBTDevice.java150
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) {