diff options
Diffstat (limited to 'java')
-rw-r--r-- | java/direct_bt/tinyb/DBTAdapter.java | 132 | ||||
-rw-r--r-- | java/jni/direct_bt/DBTAdapter.cxx | 128 | ||||
-rw-r--r-- | java/org/tinyb/AdapterSettings.java | 138 | ||||
-rw-r--r-- | java/org/tinyb/BluetoothAdapter.java | 6 | ||||
-rw-r--r-- | java/org/tinyb/BluetoothAdapterStatusListener.java (renamed from java/org/tinyb/BluetoothDeviceStatusListener.java) | 13 | ||||
-rw-r--r-- | java/org/tinyb/EIRDataType.java | 124 | ||||
-rw-r--r-- | java/org/tinyb/EIRDataTypeSet.java | 128 | ||||
-rw-r--r-- | java/tinyb/dbus/DBusAdapter.java | 4 |
8 files changed, 449 insertions, 224 deletions
diff --git a/java/direct_bt/tinyb/DBTAdapter.java b/java/direct_bt/tinyb/DBTAdapter.java index b5abf5c1..270fded3 100644 --- a/java/direct_bt/tinyb/DBTAdapter.java +++ b/java/direct_bt/tinyb/DBTAdapter.java @@ -32,14 +32,15 @@ import java.util.List; import java.util.UUID; import java.util.concurrent.atomic.AtomicInteger; +import org.tinyb.AdapterSettings; import org.tinyb.BluetoothAdapter; import org.tinyb.BluetoothDevice; import org.tinyb.BluetoothException; import org.tinyb.BluetoothManager; import org.tinyb.BluetoothNotification; import org.tinyb.BluetoothType; -import org.tinyb.EIRDataType; -import org.tinyb.BluetoothDeviceStatusListener; +import org.tinyb.EIRDataTypeSet; +import org.tinyb.BluetoothAdapterStatusListener; import org.tinyb.TransportType; public class DBTAdapter extends DBTObject implements BluetoothAdapter @@ -53,10 +54,13 @@ public class DBTAdapter extends DBTObject implements BluetoothAdapter private final Object stateLock = new Object(); private final Object discoveredDevicesLock = new Object(); - private volatile BluetoothDeviceStatusListener userDeviceStatusListener = null; - private volatile long discoveringCBHandle = 0; + private volatile BluetoothAdapterStatusListener userStatusListener = null; private volatile boolean isDiscovering = false; - private volatile long poweredCBHandle = 0; + private final long discoveringNotificationRef = 0; + + private BluetoothNotification<Boolean> discoverableNotification = null; + private BluetoothNotification<Boolean> poweredNotification = null; + private BluetoothNotification<Boolean> pairableNotification = null; private boolean isOpen = false; private List<BluetoothDevice> discoveredDevices = new ArrayList<BluetoothDevice>(); @@ -66,12 +70,17 @@ public class DBTAdapter extends DBTObject implements BluetoothAdapter super(nativeInstance, compHash(address, name)); this.address = address; this.name = name; - initImpl(this.deviceDiscoveryListener); + initImpl(this.adapterStatusListener); } @Override public synchronized void close() { stopDiscovery(); + setStatusListener(null); + disableDiscoverableNotifications(); + disableDiscoveringNotifications(); + disablePairableNotifications(); + disablePoweredNotifications(); isOpen = false; super.close(); } @@ -149,28 +158,13 @@ public class DBTAdapter extends DBTObject implements BluetoothAdapter @Override public synchronized void enablePoweredNotifications(final BluetoothNotification<Boolean> callback) { - if( 0 != poweredCBHandle ) { - removePoweredNotificationsImpl(poweredCBHandle); - poweredCBHandle = 0; - } - poweredCBHandle = addPoweredNotificationsImpl(callback); - if( 0 == poweredCBHandle ) { - throw new InternalError("addPoweredNotificationsImpl(..) == 0"); - } + poweredNotification = callback; } - private native long addPoweredNotificationsImpl(final BluetoothNotification<Boolean> callback); @Override public synchronized void disablePoweredNotifications() { - if( 0 != poweredCBHandle ) { - int count; - if( 1 != ( count = removePoweredNotificationsImpl(poweredCBHandle) ) ) { - throw new InternalError("removePoweredNotificationsImpl(0x"+Long.toHexString(poweredCBHandle)+") != 1, but "+count); - } - poweredCBHandle = 0; - } + poweredNotification = null; } - private native int removePoweredNotificationsImpl(final long callbackHandle); @Override public native void setPowered(boolean value); @@ -179,10 +173,14 @@ public class DBTAdapter extends DBTObject implements BluetoothAdapter public native boolean getDiscoverable(); @Override - public native void enableDiscoverableNotifications(BluetoothNotification<Boolean> callback); + public synchronized void enableDiscoverableNotifications(final BluetoothNotification<Boolean> callback) { + discoverableNotification = callback; + } @Override - public native void disableDiscoverableNotifications(); + public synchronized void disableDiscoverableNotifications() { + discoverableNotification = null; + } @Override public native void setDiscoverable(boolean value); @@ -200,10 +198,14 @@ public class DBTAdapter extends DBTObject implements BluetoothAdapter public native boolean getPairable(); @Override - public native void enablePairableNotifications(BluetoothNotification<Boolean> callback); + public synchronized void enablePairableNotifications(final BluetoothNotification<Boolean> callback) { + pairableNotification = callback; + } @Override - public native void disablePairableNotifications(); + public synchronized void disablePairableNotifications() { + pairableNotification = null; + } @Override public native void setPairable(boolean value); @@ -222,7 +224,7 @@ public class DBTAdapter extends DBTObject implements BluetoothAdapter /* internal */ - private native void initImpl(final BluetoothDeviceStatusListener l); + private native void initImpl(final BluetoothAdapterStatusListener l); private synchronized void open() { if( !isOpen ) { @@ -287,34 +289,15 @@ public class DBTAdapter extends DBTObject implements BluetoothAdapter public boolean getDiscovering() { return isDiscovering; } @Override - public synchronized void setDeviceStatusListener(final BluetoothDeviceStatusListener l) { - userDeviceStatusListener = l; + public synchronized void setStatusListener(final BluetoothAdapterStatusListener l) { + userStatusListener = l; } @Override - public synchronized void enableDiscoveringNotifications(final BluetoothNotification<Boolean> callback) { - if( 0 != discoveringCBHandle ) { - removeDiscoveringNotificationsImpl(discoveringCBHandle); - discoveringCBHandle = 0; - } - discoveringCBHandle = addDiscoveringNotificationsImpl(callback); - if( 0 == discoveringCBHandle ) { - throw new InternalError("addDiscoveringNotificationsImpl(..) == 0"); - } - } - private native long addDiscoveringNotificationsImpl(final BluetoothNotification<Boolean> callback); + public native void enableDiscoveringNotifications(final BluetoothNotification<Boolean> callback); @Override - public synchronized void disableDiscoveringNotifications() { - if( 0 != discoveringCBHandle ) { - int count; - if( 1 != ( count = removeDiscoveringNotificationsImpl(discoveringCBHandle) ) ) { - throw new InternalError("removeDiscoveringNotificationsImpl(0x"+Long.toHexString(discoveringCBHandle)+") != 1, but "+count); - } - discoveringCBHandle = 0; - } - } - private native int removeDiscoveringNotificationsImpl(final long callbackHandle); + public native void disableDiscoveringNotifications(); @Override public void setDiscoveryFilter(final List<UUID> uuids, final int rssi, final int pathloss, final TransportType transportType) { @@ -333,11 +316,38 @@ public class DBTAdapter extends DBTObject implements BluetoothAdapter //////////////////////////////////// - private final BluetoothDeviceStatusListener deviceDiscoveryListener = new BluetoothDeviceStatusListener() { + private final BluetoothAdapterStatusListener adapterStatusListener = new BluetoothAdapterStatusListener() { + @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) ) { + _poweredNotification.run(newmask.isSet(AdapterSettings.SettingType.POWERED)); + } + } + { + final BluetoothNotification<Boolean> _discoverableNotification = discoverableNotification; + if( null != _discoverableNotification && changedmask.isSet(AdapterSettings.SettingType.DISCOVERABLE) ) { + _discoverableNotification.run(newmask.isSet(AdapterSettings.SettingType.DISCOVERABLE)); + } + } + { + final BluetoothNotification<Boolean> _pairableNotification = pairableNotification; + if( null != _pairableNotification && changedmask.isSet(AdapterSettings.SettingType.BONDABLE) ) { + _pairableNotification.run(newmask.isSet(AdapterSettings.SettingType.BONDABLE)); + } + } + } @Override public void deviceFound(final BluetoothAdapter a, final BluetoothDevice device, final long timestamp) { - final BluetoothDeviceStatusListener l = userDeviceStatusListener; - System.err.println("DBTAdapter.DeviceStatusListener.found: "+device+" on "+a); + final BluetoothAdapterStatusListener l = userStatusListener; + System.err.println("Adapter.StatusListener.found: "+device+" on "+a); synchronized(discoveredDevicesLock) { discoveredDevices.add(device); } @@ -347,24 +357,24 @@ public class DBTAdapter extends DBTObject implements BluetoothAdapter } @Override - public void deviceUpdated(final BluetoothAdapter a, final BluetoothDevice device, final long timestamp, final EIRDataType updateMask) { - System.err.println("DBTAdapter.DeviceStatusListener.updated: "+updateMask+" of "+device+" on "+a); + 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 - userDeviceStatusListener.deviceUpdated(a, device, timestamp, updateMask); + userStatusListener.deviceUpdated(a, device, timestamp, updateMask); } @Override public void deviceConnected(final BluetoothAdapter a, final BluetoothDevice device, final long timestamp) { - final BluetoothDeviceStatusListener l = userDeviceStatusListener; - System.err.println("DBTAdapter.DeviceStatusListener.connected: "+device+" on "+a); + 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 BluetoothDeviceStatusListener l = userDeviceStatusListener; - System.err.println("DBTAdapter.DeviceStatusListener.disconnected: "+device+" on "+a); + 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/jni/direct_bt/DBTAdapter.cxx b/java/jni/direct_bt/DBTAdapter.cxx index 4085dcc4..03ab2d00 100644 --- a/java/jni/direct_bt/DBTAdapter.cxx +++ b/java/jni/direct_bt/DBTAdapter.cxx @@ -36,55 +36,80 @@ using namespace direct_bt; -static const std::string _eirDataTypeClassName("org/tinyb/EIRDataType"); -static const std::string _eirDataTypeClazzCreateArgs("(I)Lorg/tinyb/EIRDataType;"); +static const std::string _adapterSettingsClassName("org/tinyb/AdapterSettings"); +static const std::string _adapterSettingsClazzCtorArgs("(I)V"); +static const std::string _eirDataTypeSetClassName("org/tinyb/EIRDataTypeSet"); +static const std::string _eirDataTypeSetClazzCtorArgs("(I)V"); static const std::string _deviceClazzCtorArgs("(JLdirect_bt/tinyb/DBTAdapter;Ljava/lang/String;Ljava/lang/String;J)V"); +static const std::string _adapterSettingsChangedMethodArgs("(Lorg/tinyb/BluetoothAdapter;Lorg/tinyb/AdapterSettings;Lorg/tinyb/AdapterSettings;Lorg/tinyb/AdapterSettings;J)V"); static const std::string _deviceStatusMethodArgs("(Lorg/tinyb/BluetoothAdapter;Lorg/tinyb/BluetoothDevice;J)V"); -static const std::string _deviceStatusUpdateMethodArgs("(Lorg/tinyb/BluetoothAdapter;Lorg/tinyb/BluetoothDevice;JLorg/tinyb/EIRDataType;)V"); +static const std::string _deviceStatusUpdateMethodArgs("(Lorg/tinyb/BluetoothAdapter;Lorg/tinyb/BluetoothDevice;JLorg/tinyb/EIRDataTypeSet;)V"); -class DeviceStatusCallbackListener : public DBTDeviceStatusListener { +class AdapterStatusCallbackListener : public DBTAdapterStatusListener { public: /** package org.tinyb; - public interface BluetoothDeviceStatusListener { + public interface BluetoothAdapterStatusListener { + public void adapterSettingsChanged(final BluetoothAdapter adapter, + final AdapterSetting oldmask, final AdapterSetting newmask, + final AdapterSetting changedmask, final long timestamp); public void deviceFound(final BluetoothAdapter adapter, final BluetoothDevice device, final long timestamp); public void deviceUpdated(final BluetoothAdapter adapter, final BluetoothDevice device, final long timestamp, final EIRDataType updateMask); public void deviceConnected(final BluetoothAdapter adapter, final BluetoothDevice device, final long timestamp); public void deviceDisconnected(final BluetoothAdapter adapter, final BluetoothDevice device, final long timestamp); }; - */ + */ std::shared_ptr<JavaAnonObj> adapterObjRef; - std::unique_ptr<JNIGlobalRef> eirDataTypeClazzRef; - jmethodID eirDataTypeClazzCreate; + std::unique_ptr<JNIGlobalRef> adapterSettingsClazzRef; + jmethodID adapterSettingsClazzCtor; + std::unique_ptr<JNIGlobalRef> eirDataTypeSetClazzRef; + jmethodID eirDataTypeSetClazzCtor; std::unique_ptr<JNIGlobalRef> deviceClazzRef; jmethodID deviceClazzCtor; jfieldID deviceClazzTSUpdateField; std::unique_ptr<JNIGlobalRef> listenerObjRef; std::unique_ptr<JNIGlobalRef> listenerClazzRef; + jmethodID mAdapterSettingsChanged = nullptr; jmethodID mDeviceFound = nullptr; jmethodID mDeviceUpdated = nullptr; jmethodID mDeviceConnected = nullptr; jmethodID mDeviceDisconnected = nullptr; - DeviceStatusCallbackListener(JNIEnv *env, DBTAdapter *adapter, jobject deviceDiscoveryListener) { + AdapterStatusCallbackListener(JNIEnv *env, DBTAdapter *adapter, jobject deviceDiscoveryListener) { adapterObjRef = adapter->getJavaObject(); JavaGlobalObj::check(adapterObjRef, E_FILE_LINE); - // eirDataTypeClazzRef, eirDataTypeClazzCreate + // adapterSettingsClazzRef, adapterSettingsClazzCtor { - jclass eirDataTypeClazz = search_class(env, _eirDataTypeClassName.c_str()); + jclass adapterSettingsClazz = search_class(env, _adapterSettingsClassName.c_str()); java_exception_check_and_throw(env, E_FILE_LINE); - if( nullptr == eirDataTypeClazz ) { - throw InternalError("DBTDevice::java_class not found: "+_eirDataTypeClassName, E_FILE_LINE); + if( nullptr == adapterSettingsClazz ) { + throw InternalError("DBTDevice::java_class not found: "+_adapterSettingsClassName, E_FILE_LINE); } - eirDataTypeClazzRef = std::unique_ptr<JNIGlobalRef>(new JNIGlobalRef(eirDataTypeClazz)); - env->DeleteLocalRef(eirDataTypeClazz); + adapterSettingsClazzRef = std::unique_ptr<JNIGlobalRef>(new JNIGlobalRef(adapterSettingsClazz)); + env->DeleteLocalRef(adapterSettingsClazz); } - eirDataTypeClazzCreate = search_method(env, eirDataTypeClazzRef->getClass(), "create", _eirDataTypeClazzCreateArgs.c_str(), true); + adapterSettingsClazzCtor = search_method(env, adapterSettingsClazzRef->getClass(), "<init>", _adapterSettingsClazzCtorArgs.c_str(), false); java_exception_check_and_throw(env, E_FILE_LINE); - if( nullptr == eirDataTypeClazzCreate ) { - throw InternalError("EIRDataType ctor not found: "+_eirDataTypeClassName+".create"+_eirDataTypeClazzCreateArgs, E_FILE_LINE); + if( nullptr == adapterSettingsClazzCtor ) { + throw InternalError("AdapterSettings ctor not found: "+_adapterSettingsClassName+".<init>"+_adapterSettingsClazzCtorArgs, E_FILE_LINE); + } + + // eirDataTypeSetClazzRef, eirDataTypeSetClazzCtor + { + jclass eirDataTypeSetClazz = search_class(env, _eirDataTypeSetClassName.c_str()); + java_exception_check_and_throw(env, E_FILE_LINE); + if( nullptr == eirDataTypeSetClazz ) { + throw InternalError("DBTDevice::java_class not found: "+_eirDataTypeSetClassName, E_FILE_LINE); + } + eirDataTypeSetClazzRef = std::unique_ptr<JNIGlobalRef>(new JNIGlobalRef(eirDataTypeSetClazz)); + env->DeleteLocalRef(eirDataTypeSetClazz); + } + eirDataTypeSetClazzCtor = search_method(env, eirDataTypeSetClazzRef->getClass(), "<init>", _eirDataTypeSetClazzCtorArgs.c_str(), false); + java_exception_check_and_throw(env, E_FILE_LINE); + if( nullptr == eirDataTypeSetClazzCtor ) { + throw InternalError("EIRDataType ctor not found: "+_eirDataTypeSetClassName+".<init>"+_eirDataTypeSetClazzCtorArgs, E_FILE_LINE); } // deviceClazzRef, deviceClazzCtor @@ -113,30 +138,70 @@ class DeviceStatusCallbackListener : public DBTDeviceStatusListener { jclass listenerClazz = search_class(env, listenerObjRef->getObject()); java_exception_check_and_throw(env, E_FILE_LINE); if( nullptr == listenerClazz ) { - throw InternalError("BluetoothDeviceDiscoveryListener not found", E_FILE_LINE); + throw InternalError("BluetoothAdapterStatusListener not found", E_FILE_LINE); } listenerClazzRef = std::unique_ptr<JNIGlobalRef>(new JNIGlobalRef(listenerClazz)); env->DeleteLocalRef(listenerClazz); } + + + mAdapterSettingsChanged = search_method(env, listenerClazzRef->getClass(), "adapterSettingsChanged", _adapterSettingsChangedMethodArgs.c_str(), false); + java_exception_check_and_throw(env, E_FILE_LINE); + if( nullptr == mAdapterSettingsChanged ) { + throw InternalError("BluetoothAdapterStatusListener has no adapterSettingsChanged"+_adapterSettingsChangedMethodArgs+" method, for "+adapter->toString(), E_FILE_LINE); + } mDeviceFound = search_method(env, listenerClazzRef->getClass(), "deviceFound", _deviceStatusMethodArgs.c_str(), false); java_exception_check_and_throw(env, E_FILE_LINE); if( nullptr == mDeviceFound ) { - throw InternalError("BluetoothDeviceDiscoveryListener has no deviceFound"+_deviceStatusMethodArgs+" method, for "+adapter->toString(), E_FILE_LINE); + throw InternalError("BluetoothAdapterStatusListener has no deviceFound"+_deviceStatusMethodArgs+" method, for "+adapter->toString(), E_FILE_LINE); } mDeviceUpdated = search_method(env, listenerClazzRef->getClass(), "deviceUpdated", _deviceStatusUpdateMethodArgs.c_str(), false); java_exception_check_and_throw(env, E_FILE_LINE); if( nullptr == mDeviceUpdated ) { - throw InternalError("BluetoothDeviceDiscoveryListener has no deviceUpdated"+_deviceStatusMethodArgs+" method, for "+adapter->toString(), E_FILE_LINE); + throw InternalError("BluetoothAdapterStatusListener has no deviceUpdated"+_deviceStatusMethodArgs+" method, for "+adapter->toString(), E_FILE_LINE); } mDeviceConnected = search_method(env, listenerClazzRef->getClass(), "deviceConnected", _deviceStatusMethodArgs.c_str(), false); java_exception_check_and_throw(env, E_FILE_LINE); if( nullptr == mDeviceConnected ) { - throw InternalError("BluetoothDeviceDiscoveryListener has no deviceConnected"+_deviceStatusMethodArgs+" method, for "+adapter->toString(), E_FILE_LINE); + throw InternalError("BluetoothAdapterStatusListener has no deviceConnected"+_deviceStatusMethodArgs+" method, for "+adapter->toString(), E_FILE_LINE); } mDeviceDisconnected = search_method(env, listenerClazzRef->getClass(), "deviceDisconnected", _deviceStatusMethodArgs.c_str(), false); java_exception_check_and_throw(env, E_FILE_LINE); if( nullptr == mDeviceDisconnected ) { - throw InternalError("BluetoothDeviceDiscoveryListener has no deviceDisconnected"+_deviceStatusMethodArgs+" method, for "+adapter->toString(), E_FILE_LINE); + throw InternalError("BluetoothAdapterStatusListener has no deviceDisconnected"+_deviceStatusMethodArgs+" method, for "+adapter->toString(), E_FILE_LINE); + } + } + + void adapterSettingsChanged(DBTAdapter const &a, const AdapterSetting oldmask, const AdapterSetting newmask, + const AdapterSetting changedmask, const uint64_t timestamp) override { + JNIEnv *env = *jni_env; + try { + #ifdef VERBOSE_ON + fprintf(stderr, "****** Native Adapter SETTINGS_CHANGED: %s -> %s, changed %s\n", + direct_bt::adapterSettingsToString(oldmask).c_str(), + direct_bt::adapterSettingsToString(newmask).c_str(), + direct_bt::adapterSettingsToString(changedmask).c_str()); + fprintf(stderr, "Status DBTAdapter:\n"); + fprintf(stderr, "%s\n", a.toString().c_str()); + #endif + (void)a; + jobject adapterSettingOld = env->NewObject(adapterSettingsClazzRef->getClass(), adapterSettingsClazzCtor, (jint)oldmask); + if( java_exception_check(env, E_FILE_LINE) ) { return; } + JNIGlobalRef::check(adapterSettingOld, E_FILE_LINE); + + jobject adapterSettingNew = env->NewObject(adapterSettingsClazzRef->getClass(), adapterSettingsClazzCtor, (jint)newmask); + if( java_exception_check(env, E_FILE_LINE) ) { return; } + JNIGlobalRef::check(adapterSettingNew, E_FILE_LINE); + + jobject adapterSettingChanged = env->NewObject(adapterSettingsClazzRef->getClass(), adapterSettingsClazzCtor, (jint)changedmask); + if( java_exception_check(env, E_FILE_LINE) ) { return; } + JNIGlobalRef::check(adapterSettingChanged, E_FILE_LINE); + + env->CallVoidMethod(listenerObjRef->getObject(), mAdapterSettingsChanged, + JavaGlobalObj::GetObject(adapterObjRef), adapterSettingOld, adapterSettingNew, adapterSettingChanged, (jlong)timestamp); + if( java_exception_check(env, E_FILE_LINE) ) { return; } + } catch(...) { + rethrow_and_raise_java_exception(env); } } @@ -181,10 +246,13 @@ class DeviceStatusCallbackListener : public DBTDeviceStatusListener { JavaGlobalObj::check(jDeviceRef, E_FILE_LINE); env->SetLongField(JavaGlobalObj::GetObject(jDeviceRef), deviceClazzTSUpdateField, (jlong)timestamp); if( java_exception_check(env, E_FILE_LINE) ) { return; } - jobject eirDataType = env->CallStaticObjectMethod(eirDataTypeClazzRef->getClass(), eirDataTypeClazzCreate, (jint)updateMask); + + jobject eirDataTypeSet = env->NewObject(eirDataTypeSetClazzRef->getClass(), eirDataTypeSetClazzCtor, (jint)updateMask); if( java_exception_check(env, E_FILE_LINE) ) { return; } + JNIGlobalRef::check(eirDataTypeSet, E_FILE_LINE); + env->CallVoidMethod(listenerObjRef->getObject(), mDeviceUpdated, - JavaGlobalObj::GetObject(adapterObjRef), JavaGlobalObj::GetObject(jDeviceRef), (jlong)timestamp, eirDataType); + JavaGlobalObj::GetObject(adapterObjRef), JavaGlobalObj::GetObject(jDeviceRef), (jlong)timestamp, eirDataTypeSet); if( java_exception_check(env, E_FILE_LINE) ) { return; } } catch(...) { rethrow_and_raise_java_exception(env); @@ -232,16 +300,16 @@ class DeviceStatusCallbackListener : public DBTDeviceStatusListener { } }; -void Java_direct_1bt_tinyb_DBTAdapter_initImpl(JNIEnv *env, jobject obj, jobject deviceDiscoveryListener) +void Java_direct_1bt_tinyb_DBTAdapter_initImpl(JNIEnv *env, jobject obj, jobject statusListener) { - // org.tinyb.BluetoothDeviceDiscoveryListener + // org.tinyb.BluetoothAdapterStatusListener try { DBTAdapter *adapter = getInstance<DBTAdapter>(env, obj); JavaGlobalObj::check(adapter->getJavaObject(), E_FILE_LINE); // set our callback discovery listener. - DeviceStatusCallbackListener *l = new DeviceStatusCallbackListener(env, adapter, deviceDiscoveryListener); - adapter->setDeviceStatusListener(std::shared_ptr<DBTDeviceStatusListener>(l)); + AdapterStatusCallbackListener *l = new AdapterStatusCallbackListener(env, adapter, statusListener); + adapter->setStatusListener(std::shared_ptr<DBTAdapterStatusListener>(l)); } catch(...) { rethrow_and_raise_java_exception(env); } @@ -267,7 +335,7 @@ void Java_direct_1bt_tinyb_DBTAdapter_deleteImpl(JNIEnv *env, jobject obj) try { DBTAdapter *adapter = getInstance<DBTAdapter>(env, obj); DBG_PRINT("Java_direct_1bt_tinyb_DBTAdapter_deleteImpl %s", adapter->toString().c_str()); - adapter->setDeviceStatusListener(nullptr); + adapter->setStatusListener(nullptr); delete adapter; } catch(...) { rethrow_and_raise_java_exception(env); diff --git a/java/org/tinyb/AdapterSettings.java b/java/org/tinyb/AdapterSettings.java new file mode 100644 index 00000000..0fab7fd5 --- /dev/null +++ b/java/org/tinyb/AdapterSettings.java @@ -0,0 +1,138 @@ +/** + * Author: Sven Gothel <[email protected]> + * Copyright (c) 2020 Gothel Software e.K. + * Copyright (c) 2020 ZAFENA AB + * + * Permission is hereby granted, free of charge, to any person obtaining + * a copy of this software and associated documentation files (the + * "Software"), to deal in the Software without restriction, including + * without limitation the rights to use, copy, modify, merge, publish, + * distribute, sublicense, and/or sell copies of the Software, and to + * permit persons to whom the Software is furnished to do so, subject to + * the following conditions: + * + * The above copyright notice and this permission notice shall be + * included in all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, + * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF + * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND + * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE + * LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION + * OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION + * WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + */ +package org.tinyb; + +public class AdapterSettings { + + public enum SettingType { + NONE ( 0), + POWERED (0x00000001), + CONNECTABLE (0x00000002), + FAST_CONNECTABLE (0x00000004), + DISCOVERABLE (0x00000008), + BONDABLE (0x00000010), + LINK_SECURITY (0x00000020), + SSP (0x00000040), + BREDR (0x00000080), + HS (0x00000100), + LE (0x00000200), + ADVERTISING (0x00000400), + SECURE_CONN (0x00000800), + DEBUG_KEYS (0x00001000), + PRIVACY (0x00002000), + CONFIGURATION (0x00004000), + STATIC_ADDRESS (0x00008000), + PHY_CONFIGURATION (0x00010000); + + SettingType(final int v) { value = v; } + public final int value; + } + + public int mask; + + public AdapterSettings(final int v) { + mask = v; + } + + public boolean isSet(final SettingType bit) { return 0 != ( mask & bit.value ); } + public void set(final SettingType bit) { mask = mask | bit.value; } + + public String toString() { + int count = 0; + final StringBuilder out = new StringBuilder(); + if( isSet(SettingType.POWERED) ) { + out.append(SettingType.POWERED.name()); count++; + } + if( isSet(SettingType.CONNECTABLE) ) { + if( 0 < count ) { out.append(", "); } + out.append(SettingType.CONNECTABLE.name()); count++; + } + if( isSet(SettingType.FAST_CONNECTABLE) ) { + if( 0 < count ) { out.append(", "); } + out.append(SettingType.FAST_CONNECTABLE.name()); count++; + } + if( isSet(SettingType.DISCOVERABLE) ) { + if( 0 < count ) { out.append(", "); } + out.append(SettingType.DISCOVERABLE.name()); count++; + } + if( isSet(SettingType.BONDABLE) ) { + if( 0 < count ) { out.append(", "); } + out.append(SettingType.BONDABLE.name()); count++; + } + if( isSet(SettingType.LINK_SECURITY) ) { + if( 0 < count ) { out.append(", "); } + out.append(SettingType.LINK_SECURITY.name()); count++; + } + if( isSet(SettingType.SSP) ) { + if( 0 < count ) { out.append(", "); } + out.append(SettingType.SSP.name()); count++; + } + if( isSet(SettingType.BREDR) ) { + if( 0 < count ) { out.append(", "); } + out.append(SettingType.BREDR.name()); count++; + } + if( isSet(SettingType.HS) ) { + if( 0 < count ) { out.append(", "); } + out.append(SettingType.HS.name()); count++; + } + if( isSet(SettingType.LE) ) { + if( 0 < count ) { out.append(", "); } + out.append(SettingType.LE.name()); count++; + } + if( isSet(SettingType.ADVERTISING) ) { + if( 0 < count ) { out.append(", "); } + out.append(SettingType.ADVERTISING.name()); count++; + } + if( isSet(SettingType.SECURE_CONN) ) { + if( 0 < count ) { out.append(", "); } + out.append(SettingType.SECURE_CONN.name()); count++; + } + if( isSet(SettingType.DEBUG_KEYS) ) { + if( 0 < count ) { out.append(", "); } + out.append(SettingType.DEBUG_KEYS.name()); count++; + } + if( isSet(SettingType.PRIVACY) ) { + if( 0 < count ) { out.append(", "); } + out.append(SettingType.PRIVACY.name()); count++; + } + if( isSet(SettingType.CONFIGURATION) ) { + if( 0 < count ) { out.append(", "); } + out.append(SettingType.CONFIGURATION.name()); count++; + } + if( isSet(SettingType.STATIC_ADDRESS) ) { + if( 0 < count ) { out.append(", "); } + out.append(SettingType.STATIC_ADDRESS.name()); count++; + } + if( isSet(SettingType.PHY_CONFIGURATION) ) { + if( 0 < count ) { out.append(", "); } + out.append(SettingType.PHY_CONFIGURATION.name()); count++; + } + if( 1 < count ) { + out.insert(0, "["); + out.append("]"); + } + return out.toString(); + } +} diff --git a/java/org/tinyb/BluetoothAdapter.java b/java/org/tinyb/BluetoothAdapter.java index 4a989500..bf608e90 100644 --- a/java/org/tinyb/BluetoothAdapter.java +++ b/java/org/tinyb/BluetoothAdapter.java @@ -242,10 +242,10 @@ public interface BluetoothAdapter extends BluetoothObject public boolean getDiscovering(); /** - * Sets the {@link BluetoothDeviceStatusListener} for the respective device status events. - * @param listener A {@link BluetoothDeviceStatusListener} instance, or {@code null} to disable notifications. + * Sets the {@link BluetoothAdapterStatusListener} for the respective device status events. + * @param listener A {@link BluetoothAdapterStatusListener} instance, or {@code null} to disable notifications. */ - public void setDeviceStatusListener(final BluetoothDeviceStatusListener listener); + public void setStatusListener(final BluetoothAdapterStatusListener listener); /** * Enables notifications for the discovering property and calls run function of the diff --git a/java/org/tinyb/BluetoothDeviceStatusListener.java b/java/org/tinyb/BluetoothAdapterStatusListener.java index 3220d106..b6262a1e 100644 --- a/java/org/tinyb/BluetoothDeviceStatusListener.java +++ b/java/org/tinyb/BluetoothAdapterStatusListener.java @@ -26,17 +26,22 @@ package org.tinyb; /** - * {@link BluetoothDevice} listener for the respective {@link BluetoothDevice} discovery events: Added, updated and removed. + * {@link BluetoothAdapter} status listener for {@link BluetoothDevice} discovery events: Added, updated and removed; + * as well as for certain {@link BluetoothAdapter} events. * <p> * A listener instance may be attached to a {@link BluetoothAdapter} via - * {@link BluetoothAdapter#setDeviceStatusListener(BluetoothDeviceDiscoveryListener)}. + * {@link BluetoothAdapter#setStatusListener(BluetoothDeviceDiscoveryListener)}. * </p> */ -public interface BluetoothDeviceStatusListener { +public interface BluetoothAdapterStatusListener { + /** A {@link BluetoothAdapter} setting has been changed. */ + public void adapterSettingsChanged(final BluetoothAdapter adapter, + final AdapterSettings oldmask, final AdapterSettings newmask, + final AdapterSettings changedmask, final long timestamp); /** A {@link BluetoothDevice} has been newly discovered. */ public void deviceFound(final BluetoothAdapter adapter, final BluetoothDevice device, final long timestamp); /** An already discovered {@link BluetoothDevice} has been updated. */ - public void deviceUpdated(final BluetoothAdapter adapter, final BluetoothDevice device, final long timestamp, final EIRDataType updateMask); + public void deviceUpdated(final BluetoothAdapter adapter, final BluetoothDevice device, final long timestamp, final EIRDataTypeSet updateMask); /** {@link BluetoothDevice} has been connected. */ public void deviceConnected(final BluetoothAdapter adapter, final BluetoothDevice device, final long timestamp); /** {@link BluetoothDevice} has been disconnected. */ diff --git a/java/org/tinyb/EIRDataType.java b/java/org/tinyb/EIRDataType.java deleted file mode 100644 index 8134b20e..00000000 --- a/java/org/tinyb/EIRDataType.java +++ /dev/null @@ -1,124 +0,0 @@ -/** - * Author: Sven Gothel <[email protected]> - * Copyright (c) 2020 Gothel Software e.K. - * Copyright (c) 2020 ZAFENA AB - * - * Permission is hereby granted, free of charge, to any person obtaining - * a copy of this software and associated documentation files (the - * "Software"), to deal in the Software without restriction, including - * without limitation the rights to use, copy, modify, merge, publish, - * distribute, sublicense, and/or sell copies of the Software, and to - * permit persons to whom the Software is furnished to do so, subject to - * the following conditions: - * - * The above copyright notice and this permission notice shall be - * included in all copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, - * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF - * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND - * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE - * LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION - * OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION - * WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. - */ -package org.tinyb; - -public enum EIRDataType { - NONE ( 0), - EVT_TYPE (1 << 0), - BDADDR_TYPE (1 << 1), - BDADDR (1 << 2), - FLAGS (1 << 3), - NAME (1 << 4), - NAME_SHORT (1 << 5), - RSSI (1 << 6), - TX_POWER (1 << 7), - MANUF_DATA (1 << 8), - DEVICE_CLASS (1 << 9), - APPEARANCE (1 << 10), - HASH (1 << 11), - RANDOMIZER (1 << 12), - DEVICE_ID (1 << 13), - SERVICE_UUID (1 << 30); - - EIRDataType(final int v) { mask = v; } - public static EIRDataType create(final int v) { - final EIRDataType r = NONE; - r.mask = v; - return r; - } - - public int mask; - public boolean isSet(final EIRDataType bit) { return 0 != ( mask & bit.mask ); } - public void set(final EIRDataType bit) { mask = mask | bit.mask; } - - public String toString() { - int count = 0; - final StringBuilder out = new StringBuilder(); - if( isSet(EVT_TYPE) ) { - out.append(EVT_TYPE.name()); count++; - } - if( isSet(BDADDR_TYPE) ) { - if( 0 < count ) { out.append(", "); } - out.append(BDADDR_TYPE.name()); count++; - } - if( isSet(BDADDR) ) { - if( 0 < count ) { out.append(", "); } - out.append(BDADDR.name()); count++; - } - if( isSet(FLAGS) ) { - if( 0 < count ) { out.append(", "); } - out.append(FLAGS.name()); count++; - } - if( isSet(NAME) ) { - if( 0 < count ) { out.append(", "); } - out.append(NAME.name()); count++; - } - if( isSet(NAME_SHORT) ) { - if( 0 < count ) { out.append(", "); } - out.append(NAME_SHORT.name()); count++; - } - if( isSet(RSSI) ) { - if( 0 < count ) { out.append(", "); } - out.append(RSSI.name()); count++; - } - if( isSet(TX_POWER) ) { - if( 0 < count ) { out.append(", "); } - out.append(TX_POWER.name()); count++; - } - if( isSet(MANUF_DATA) ) { - if( 0 < count ) { out.append(", "); } - out.append(MANUF_DATA.name()); count++; - } - if( isSet(DEVICE_CLASS) ) { - if( 0 < count ) { out.append(", "); } - out.append(DEVICE_CLASS.name()); count++; - } - if( isSet(APPEARANCE) ) { - if( 0 < count ) { out.append(", "); } - out.append(APPEARANCE.name()); count++; - } - if( isSet(HASH) ) { - if( 0 < count ) { out.append(", "); } - out.append(HASH.name()); count++; - } - if( isSet(RANDOMIZER) ) { - if( 0 < count ) { out.append(", "); } - out.append(RANDOMIZER.name()); count++; - } - if( isSet(DEVICE_ID) ) { - if( 0 < count ) { out.append(", "); } - out.append(DEVICE_ID.name()); count++; - } - if( isSet(SERVICE_UUID) ) { - if( 0 < count ) { out.append(", "); } - out.append(SERVICE_UUID.name()); count++; - } - if( 1 < count ) { - out.insert(0, "["); - out.append("]"); - } - return out.toString(); - } -} diff --git a/java/org/tinyb/EIRDataTypeSet.java b/java/org/tinyb/EIRDataTypeSet.java new file mode 100644 index 00000000..258066d8 --- /dev/null +++ b/java/org/tinyb/EIRDataTypeSet.java @@ -0,0 +1,128 @@ +/** + * Author: Sven Gothel <[email protected]> + * Copyright (c) 2020 Gothel Software e.K. + * Copyright (c) 2020 ZAFENA AB + * + * Permission is hereby granted, free of charge, to any person obtaining + * a copy of this software and associated documentation files (the + * "Software"), to deal in the Software without restriction, including + * without limitation the rights to use, copy, modify, merge, publish, + * distribute, sublicense, and/or sell copies of the Software, and to + * permit persons to whom the Software is furnished to do so, subject to + * the following conditions: + * + * The above copyright notice and this permission notice shall be + * included in all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, + * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF + * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND + * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE + * LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION + * OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION + * WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + */ +package org.tinyb; + +public class EIRDataTypeSet { + + public enum DataType { + NONE ( 0), + EVT_TYPE (1 << 0), + BDADDR_TYPE (1 << 1), + BDADDR (1 << 2), + FLAGS (1 << 3), + NAME (1 << 4), + NAME_SHORT (1 << 5), + RSSI (1 << 6), + TX_POWER (1 << 7), + MANUF_DATA (1 << 8), + DEVICE_CLASS (1 << 9), + APPEARANCE (1 << 10), + HASH (1 << 11), + RANDOMIZER (1 << 12), + DEVICE_ID (1 << 13), + SERVICE_UUID (1 << 30); + + DataType(final int v) { value = v; } + public final int value; + } + + public int mask; + + public EIRDataTypeSet(final int v) { + mask = v; + } + + public boolean isSet(final DataType bit) { return 0 != ( mask & bit.value ); } + public void set(final DataType bit) { mask = mask | bit.value; } + + public String toString() { + int count = 0; + final StringBuilder out = new StringBuilder(); + if( isSet(DataType.EVT_TYPE) ) { + out.append(DataType.EVT_TYPE.name()); count++; + } + if( isSet(DataType.BDADDR_TYPE) ) { + if( 0 < count ) { out.append(", "); } + out.append(DataType.BDADDR_TYPE.name()); count++; + } + if( isSet(DataType.BDADDR) ) { + if( 0 < count ) { out.append(", "); } + out.append(DataType.BDADDR.name()); count++; + } + if( isSet(DataType.FLAGS) ) { + if( 0 < count ) { out.append(", "); } + out.append(DataType.FLAGS.name()); count++; + } + if( isSet(DataType.NAME) ) { + if( 0 < count ) { out.append(", "); } + out.append(DataType.NAME.name()); count++; + } + if( isSet(DataType.NAME_SHORT) ) { + if( 0 < count ) { out.append(", "); } + out.append(DataType.NAME_SHORT.name()); count++; + } + if( isSet(DataType.RSSI) ) { + if( 0 < count ) { out.append(", "); } + out.append(DataType.RSSI.name()); count++; + } + if( isSet(DataType.TX_POWER) ) { + if( 0 < count ) { out.append(", "); } + out.append(DataType.TX_POWER.name()); count++; + } + if( isSet(DataType.MANUF_DATA) ) { + if( 0 < count ) { out.append(", "); } + out.append(DataType.MANUF_DATA.name()); count++; + } + if( isSet(DataType.DEVICE_CLASS) ) { + if( 0 < count ) { out.append(", "); } + out.append(DataType.DEVICE_CLASS.name()); count++; + } + if( isSet(DataType.APPEARANCE) ) { + if( 0 < count ) { out.append(", "); } + out.append(DataType.APPEARANCE.name()); count++; + } + if( isSet(DataType.HASH) ) { + if( 0 < count ) { out.append(", "); } + out.append(DataType.HASH.name()); count++; + } + if( isSet(DataType.RANDOMIZER) ) { + if( 0 < count ) { out.append(", "); } + out.append(DataType.RANDOMIZER.name()); count++; + } + if( isSet(DataType.DEVICE_ID) ) { + if( 0 < count ) { out.append(", "); } + out.append(DataType.DEVICE_ID.name()); count++; + } + if( isSet(DataType.SERVICE_UUID) ) { + if( 0 < count ) { out.append(", "); } + out.append(DataType.SERVICE_UUID.name()); count++; + } + if( 1 < count ) { + out.insert(0, "["); + out.append("]"); + } + return out.toString(); + } +} diff --git a/java/tinyb/dbus/DBusAdapter.java b/java/tinyb/dbus/DBusAdapter.java index b49e9fc7..0fa8b787 100644 --- a/java/tinyb/dbus/DBusAdapter.java +++ b/java/tinyb/dbus/DBusAdapter.java @@ -35,7 +35,7 @@ import java.util.UUID; import org.tinyb.BluetoothAdapter; import org.tinyb.BluetoothDevice; -import org.tinyb.BluetoothDeviceStatusListener; +import org.tinyb.BluetoothAdapterStatusListener; import org.tinyb.BluetoothException; import org.tinyb.BluetoothManager; import org.tinyb.BluetoothNotification; @@ -149,7 +149,7 @@ public class DBusAdapter extends DBusObject implements BluetoothAdapter public native boolean getDiscovering(); @Override - public void setDeviceStatusListener(final BluetoothDeviceStatusListener l) { + public void setStatusListener(final BluetoothAdapterStatusListener l) { throw new UnsupportedOperationException(); // FIXME } |