diff options
author | Sven Gothel <[email protected]> | 2020-05-10 06:03:59 +0200 |
---|---|---|
committer | Sven Gothel <[email protected]> | 2020-05-10 06:03:59 +0200 |
commit | 0f53fde528dea4470d152d30f33f357dde1b2e10 (patch) | |
tree | e504202c2a92bd16299ee1204ed5b2130ecb8aa4 /java/direct_bt | |
parent | 7adcc61246e0948041e77c4eb45c75c1f46ea2b4 (diff) |
[Bluetooth]AdapterStatusListener: Renamed; Using a list instead of one-shot callback; Mutable callbacks for_each...
[Bluetooth]AdapterStatusListener:
- Renamed BluetoothAdapterStatusListener -> AdapterStatusListener
- Using a list instead of one-shot callback: Allows utilizing information from multiple actors,
which also allows a more efficient implementation of the tinyb interfaces.
- Mutable callbacks for_each...: BasicAlgos.hpp adds for_each_idx_mtx(..) template algos,
allowing to perform one UnaryFunction via indices and utilizing mutex lock
for thread safety. This pattern reduces code complexity, as we need to
use the visitor model for the listener multiple times.
- Java: DBTDevice's AdapterStatusListener hook performs certain TinyB one-shot callbacks
Diffstat (limited to 'java/direct_bt')
-rw-r--r-- | java/direct_bt/tinyb/DBTAdapter.java | 35 | ||||
-rw-r--r-- | java/direct_bt/tinyb/DBTDevice.java | 87 |
2 files changed, 95 insertions, 27 deletions
diff --git a/java/direct_bt/tinyb/DBTAdapter.java b/java/direct_bt/tinyb/DBTAdapter.java index 270fded3..11795f28 100644 --- a/java/direct_bt/tinyb/DBTAdapter.java +++ b/java/direct_bt/tinyb/DBTAdapter.java @@ -40,7 +40,7 @@ import org.tinyb.BluetoothManager; import org.tinyb.BluetoothNotification; import org.tinyb.BluetoothType; import org.tinyb.EIRDataTypeSet; -import org.tinyb.BluetoothAdapterStatusListener; +import org.tinyb.AdapterStatusListener; import org.tinyb.TransportType; public class DBTAdapter extends DBTObject implements BluetoothAdapter @@ -54,7 +54,6 @@ public class DBTAdapter extends DBTObject implements BluetoothAdapter private final Object stateLock = new Object(); private final Object discoveredDevicesLock = new Object(); - private volatile BluetoothAdapterStatusListener userStatusListener = null; private volatile boolean isDiscovering = false; private final long discoveringNotificationRef = 0; @@ -70,13 +69,13 @@ public class DBTAdapter extends DBTObject implements BluetoothAdapter super(nativeInstance, compHash(address, name)); this.address = address; this.name = name; - initImpl(this.adapterStatusListener); + addStatusListener(this.statusListener); } @Override public synchronized void close() { stopDiscovery(); - setStatusListener(null); + removeStatusListener(this.statusListener); disableDiscoverableNotifications(); disableDiscoveringNotifications(); disablePairableNotifications(); @@ -224,8 +223,6 @@ public class DBTAdapter extends DBTObject implements BluetoothAdapter /* internal */ - private native void initImpl(final BluetoothAdapterStatusListener l); - private synchronized void open() { if( !isOpen ) { isOpen = openImpl(); @@ -289,9 +286,10 @@ public class DBTAdapter extends DBTObject implements BluetoothAdapter public boolean getDiscovering() { return isDiscovering; } @Override - public synchronized void setStatusListener(final BluetoothAdapterStatusListener l) { - userStatusListener = l; - } + public native boolean addStatusListener(final AdapterStatusListener l); + + @Override + public native boolean removeStatusListener(final AdapterStatusListener l); @Override public native void enableDiscoveringNotifications(final BluetoothNotification<Boolean> callback); @@ -316,15 +314,11 @@ public class DBTAdapter extends DBTObject implements BluetoothAdapter //////////////////////////////////// - private final BluetoothAdapterStatusListener adapterStatusListener = new BluetoothAdapterStatusListener() { + private final AdapterStatusListener statusListener = new AdapterStatusListener() { @Override public void adapterSettingsChanged(final BluetoothAdapter a, final AdapterSettings oldmask, final AdapterSettings newmask, final AdapterSettings changedmask, final long timestamp) { - final BluetoothAdapterStatusListener l = userStatusListener; System.err.println("Adapter.StatusListener.settings: "+oldmask+" -> "+newmask+", changed "+changedmask+" on "+a); - if( null != l ) { - l.adapterSettingsChanged(a, oldmask, newmask, changedmask, timestamp); - } { final BluetoothNotification<Boolean> _poweredNotification = poweredNotification; if( null != _poweredNotification && changedmask.isSet(AdapterSettings.SettingType.POWERED) ) { @@ -346,38 +340,25 @@ public class DBTAdapter extends DBTObject implements BluetoothAdapter } @Override public void deviceFound(final BluetoothAdapter a, final BluetoothDevice device, final long timestamp) { - final BluetoothAdapterStatusListener l = userStatusListener; System.err.println("Adapter.StatusListener.found: "+device+" on "+a); synchronized(discoveredDevicesLock) { discoveredDevices.add(device); } - if( null != l ) { - l.deviceFound(a, device, timestamp); - } } @Override public void deviceUpdated(final BluetoothAdapter a, final BluetoothDevice device, final long timestamp, final EIRDataTypeSet updateMask) { System.err.println("Adapter.StatusListener.updated: "+updateMask+" of "+device+" on "+a); // nop on discoveredDevices - userStatusListener.deviceUpdated(a, device, timestamp, updateMask); } @Override public void deviceConnected(final BluetoothAdapter a, final BluetoothDevice device, final long timestamp) { - final BluetoothAdapterStatusListener l = userStatusListener; System.err.println("Adapter.StatusListener.connected: "+device+" on "+a); - if( null != l ) { - l.deviceConnected(a, device, timestamp); - } } @Override public void deviceDisconnected(final BluetoothAdapter a, final BluetoothDevice device, final long timestamp) { - final BluetoothAdapterStatusListener l = userStatusListener; System.err.println("Adapter.StatusListener.disconnected: "+device+" on "+a); - if( null != l ) { - l.deviceDisconnected(a, device, timestamp); - } } }; } diff --git a/java/direct_bt/tinyb/DBTDevice.java b/java/direct_bt/tinyb/DBTDevice.java index e2ef4d70..7e482137 100644 --- a/java/direct_bt/tinyb/DBTDevice.java +++ b/java/direct_bt/tinyb/DBTDevice.java @@ -28,6 +28,9 @@ package direct_bt.tinyb; import java.util.List; import java.util.Map; +import org.tinyb.AdapterSettings; +import org.tinyb.BluetoothAdapter; +import org.tinyb.AdapterStatusListener; import org.tinyb.BluetoothDevice; import org.tinyb.BluetoothException; import org.tinyb.BluetoothGattService; @@ -35,6 +38,7 @@ import org.tinyb.BluetoothManager; import org.tinyb.BluetoothNotification; import org.tinyb.BluetoothType; import org.tinyb.BluetoothUtils; +import org.tinyb.EIRDataTypeSet; public class DBTDevice extends DBTObject implements BluetoothDevice { @@ -44,6 +48,58 @@ public class DBTDevice extends DBTObject implements BluetoothDevice private final long ts_creation; long ts_update; + private final long connectedNotificationRef = 0; + private boolean connected = false; + private final Object userCallbackLock = new Object(); + private BluetoothNotification<Boolean> userConnectedNotificationsCB = null; + private BluetoothNotification<Short> userRSSINotificationsCB = null; + private BluetoothNotification<Map<Short, byte[]> > userManufDataNotificationsCB = null; + private BluetoothNotification<Boolean> userServicesResolvedNotificationsCB = null; + private boolean servicesResolved = false; + private short appearance = 0; + + final AdapterStatusListener statusListener = new AdapterStatusListener() { + @Override + public void deviceUpdated(final BluetoothAdapter adapter, final BluetoothDevice device, final long timestamp, final EIRDataTypeSet updateMask) { + if( device != DBTDevice.this ) { + return; + } + 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()); + } + } + } + @Override + public void deviceConnected(final BluetoothAdapter adapter, final BluetoothDevice device, final long timestamp) { + if( device != DBTDevice.this ) { + return; + } + connected = true; + synchronized(userCallbackLock) { + if( null != userConnectedNotificationsCB ) { + userConnectedNotificationsCB.run(true); + } + } + } + @Override + public void deviceDisconnected(final BluetoothAdapter adapter, final BluetoothDevice device, final long timestamp) { + if( device != DBTDevice.this ) { + return; + } + connected = false; + synchronized(userCallbackLock) { + if( null != userConnectedNotificationsCB ) { + userConnectedNotificationsCB.run(false); + } + } + } + }; + + /* pp */ DBTDevice(final long nativeInstance, final DBTAdapter adptr, final String address, final String name, final long ts_creation) { super(nativeInstance, compHash(address, name)); @@ -52,7 +108,38 @@ public class DBTDevice extends DBTObject implements BluetoothDevice this.name = name; this.ts_creation = ts_creation; ts_update = ts_creation; + appearance = 0; initImpl(); + // this.adapter.addStatusListener(statusListener); + this.addStatusListener(statusListener); + } + + /** + * Special proxy of {@link DBTAdapter#addStatusListener(AdapterStatusListener)} + * to be used from out constructor called via native deviceFound callback! + * <p> + * FIXME: Without this proxy hook, we end up in a crash within the addStatusListener(..). + * FIXME: Analyze reason! Triage! + * </p> + */ + private native boolean addStatusListener(final AdapterStatusListener l); + + @Override + public synchronized void close() { + disconnect(); + + disableConnectedNotifications(); + disableRSSINotifications(); + disableManufacturerDataNotifications(); + disableServicesResolvedNotifications(); + + disableBlockedNotifications(); + disablePairedNotifications(); + disableServiceDataNotifications(); + disableTrustedNotifications(); + + this.adapter.removeStatusListener(statusListener); + super.close(); } @Override |