diff options
author | Sven Gothel <[email protected]> | 2020-05-12 06:39:36 +0200 |
---|---|---|
committer | Sven Gothel <[email protected]> | 2020-05-12 06:39:36 +0200 |
commit | d198176d2fbe5c88cf81ffb647abced753af52c2 (patch) | |
tree | 6d41698d308520adf7fd743e718724343e48292c | |
parent | 604e03053942521c1e104b0c473864ff4139b939 (diff) |
Fixing multiple Java/C++ Lifecycle Issues (DBTDevice, add ShutdownHook, ..)
DBTDevice
- don't native delete @ JNI deleteImpl, adapter holds share_ptr ownership
- only create its java object 1st time @ deviceFound callback of JNI DBTAdapter
DBTAdapter::mgmtEvDeviceFoundCB
- in case of !discoveredDeviceList but sharedDeviceList,
the device shall be updated first,
then deviceFound callbacks issued, allowing listener to act and register,
then deviceUpdate callbacks issued, allowing data update on existing actors
DBTManager.java:
- Add ShutdownHook calling custom hooks and shutdown()
- shutdown() in depth shutdown:
-- iterated through all adapter issueing adapter.close()
-- Adapter.close() iterates through all discoveredDevices issuing close()
DBTDevice.java:
- adds adapter JNI proxy to removeStatusListener(..), same 'to be resolved' issue
as with addStatusListener(..).
-rw-r--r-- | api/direct_bt/JavaUplink.hpp | 12 | ||||
-rw-r--r-- | examples/java/ScannerTinyB01.java | 18 | ||||
-rw-r--r-- | java/direct_bt/tinyb/DBTAdapter.java | 14 | ||||
-rw-r--r-- | java/direct_bt/tinyb/DBTDevice.java | 4 | ||||
-rw-r--r-- | java/direct_bt/tinyb/DBTManager.java | 88 | ||||
-rw-r--r-- | java/jni/JNIMem.cxx | 5 | ||||
-rw-r--r-- | java/jni/JNIMem.hpp | 3 | ||||
-rw-r--r-- | java/jni/direct_bt/DBTAdapter.cxx | 31 | ||||
-rw-r--r-- | java/jni/direct_bt/DBTDevice.cxx | 19 | ||||
-rw-r--r-- | java/jni/direct_bt/DBTManager.cxx | 7 | ||||
-rw-r--r-- | java/jni/direct_bt/DBTNativeDownlink.cxx | 4 | ||||
-rw-r--r-- | java/jni/direct_bt/helper_dbt.hpp | 13 | ||||
-rw-r--r-- | src/direct_bt/DBTAdapter.cpp | 10 | ||||
-rw-r--r-- | src/direct_bt/DBTDevice.cpp | 5 |
14 files changed, 201 insertions, 32 deletions
diff --git a/api/direct_bt/JavaUplink.hpp b/api/direct_bt/JavaUplink.hpp index 86c7251e..bea38e4f 100644 --- a/api/direct_bt/JavaUplink.hpp +++ b/api/direct_bt/JavaUplink.hpp @@ -37,6 +37,9 @@ namespace direct_bt { public: virtual ~JavaAnonObj() { } virtual std::string toString() const { return "JavaAnonObj[???]"; } + + /** Clears the java reference, i.e. nulling it, without deleting the global reference via JNI. */ + virtual void clear() { } }; class JavaUplink { @@ -50,8 +53,17 @@ namespace direct_bt { std::string javaObjectToString() const { return nullptr == javaObjectRef ? "JavaAnonObj[null]" : javaObjectRef->toString(); } std::shared_ptr<JavaAnonObj> getJavaObject() { return javaObjectRef; } + + /** Assigns a new shared JavaAnonObj reference, replaced item might be deleted via JNI from dtor */ void setJavaObject(std::shared_ptr<JavaAnonObj> objRef) { javaObjectRef = objRef; } + /** Clears the java reference, i.e. nulling it, without deleting the global reference via JNI. */ + void clearJavaObject() { + if( nullptr != javaObjectRef ) { + javaObjectRef->clear(); + } + } + virtual ~JavaUplink() { javaObjectRef = nullptr; } diff --git a/examples/java/ScannerTinyB01.java b/examples/java/ScannerTinyB01.java index ada30693..aea70c40 100644 --- a/examples/java/ScannerTinyB01.java +++ b/examples/java/ScannerTinyB01.java @@ -45,10 +45,11 @@ public class ScannerTinyB01 { static { System.setProperty("org.tinyb.verbose", "true"); } - /** 60,000 milliseconds */ - static long TO_DISCOVER = 60000; + /** 10,000 milliseconds */ + static long TO_DISCOVER = 10000; public static void main(final String[] args) throws InterruptedException { + long t0_discovery = TO_DISCOVER; int factory = 0; int dev_id = 0; // default int mode = 0; @@ -67,6 +68,8 @@ public class ScannerTinyB01 { mode = Integer.valueOf(args[++i]).intValue(); } else if( arg.equals("-factory") && args.length > (i+1) ) { factory = Integer.valueOf(args[++i]).intValue(); + } else if( arg.equals("-t0_discovery") && args.length > (i+1) ) { + t0_discovery = Long.valueOf(args[++i]).longValue(); } else if( arg.equals("-forever") ) { forever = true; } @@ -201,14 +204,17 @@ public class ScannerTinyB01 { if( 0 == mode ) { synchronized(matchingDiscoveredDeviceBucket) { - while( null == matchingDiscoveredDeviceBucket[0] ) { - matchingDiscoveredDeviceBucket.wait(TO_DISCOVER); + boolean timeout = false; + while( !timeout && null == matchingDiscoveredDeviceBucket[0] ) { + matchingDiscoveredDeviceBucket.wait(t0_discovery); + final long tn = BluetoothUtils.getCurrentMilliseconds(); + timeout = ( tn - t0 ) > t0_discovery; } sensor = matchingDiscoveredDeviceBucket[0]; matchingDiscoveredDeviceBucket[0] = null; } } else if( 1 == mode ) { - sensor = adapter.find(null, mac, TO_DISCOVER); + sensor = adapter.find(null, mac, t0_discovery); } else { boolean timeout = false; while( null == sensor && !timeout ) { @@ -220,7 +226,7 @@ public class ScannerTinyB01 { break; } final long tn = BluetoothUtils.getCurrentMilliseconds(); - timeout = ( tn - t0 ) > TO_DISCOVER; + timeout = ( tn - t0 ) > t0_discovery; } } } diff --git a/java/direct_bt/tinyb/DBTAdapter.java b/java/direct_bt/tinyb/DBTAdapter.java index 71ab8394..77404d36 100644 --- a/java/direct_bt/tinyb/DBTAdapter.java +++ b/java/direct_bt/tinyb/DBTAdapter.java @@ -65,7 +65,7 @@ public class DBTAdapter extends DBTObject implements BluetoothAdapter private boolean isPairable = false; private boolean isOpen = false; - private List<BluetoothDevice> discoveredDevices = new ArrayList<BluetoothDevice>(); + private final List<BluetoothDevice> discoveredDevices = new ArrayList<BluetoothDevice>(); /* pp */ DBTAdapter(final long nativeInstance, final String address, final String name) { @@ -78,11 +78,21 @@ public class DBTAdapter extends DBTObject implements BluetoothAdapter @Override public synchronized void close() { stopDiscovery(); + + for(final Iterator<BluetoothDevice> id = discoveredDevices.iterator(); id.hasNext(); ) { + final BluetoothDevice d = id.next(); + d.close(); + } + removeStatusListener(this.statusListener); disableDiscoverableNotifications(); disableDiscoveringNotifications(); disablePairableNotifications(); disablePoweredNotifications(); + + removeDevicesImpl(); + discoveredDevices.clear(); + isOpen = false; super.close(); } @@ -285,7 +295,7 @@ public class DBTAdapter extends DBTObject implements BluetoothAdapter private int removeDiscoveredDevices() { synchronized(discoveredDevicesLock) { final int n = discoveredDevices.size(); - discoveredDevices = new ArrayList<BluetoothDevice>(); + discoveredDevices.clear(); return n; } } diff --git a/java/direct_bt/tinyb/DBTDevice.java b/java/direct_bt/tinyb/DBTDevice.java index 9fc0a806..ac4e50e8 100644 --- a/java/direct_bt/tinyb/DBTDevice.java +++ b/java/direct_bt/tinyb/DBTDevice.java @@ -124,6 +124,7 @@ public class DBTDevice extends DBTObject implements BluetoothDevice * </p> */ private native boolean addStatusListener(final AdapterStatusListener l); + private native boolean removeStatusListener(final AdapterStatusListener l); @Override public synchronized void close() { @@ -139,7 +140,8 @@ public class DBTDevice extends DBTObject implements BluetoothDevice disableServiceDataNotifications(); disableTrustedNotifications(); - this.adapter.removeStatusListener(statusListener); + // this.adapter.removeStatusListener(statusListener); + removeStatusListener(statusListener); super.close(); } diff --git a/java/direct_bt/tinyb/DBTManager.java b/java/direct_bt/tinyb/DBTManager.java index 4438c66f..e458403d 100644 --- a/java/direct_bt/tinyb/DBTManager.java +++ b/java/direct_bt/tinyb/DBTManager.java @@ -25,7 +25,10 @@ package direct_bt.tinyb; +import java.security.AccessController; +import java.security.PrivilegedAction; import java.util.ArrayList; +import java.util.Iterator; import java.util.List; import org.tinyb.BluetoothAdapter; @@ -38,6 +41,87 @@ import org.tinyb.BluetoothType; public class DBTManager implements BluetoothManager { + protected static final boolean DEBUG = true; + + private static volatile boolean isJVMShuttingDown = false; + private static final List<Runnable> userShutdownHooks = new ArrayList<Runnable>(); + + static { + AccessController.doPrivileged(new PrivilegedAction<Object>() { + @Override + public Object run() { + Runtime.getRuntime().addShutdownHook( + new Thread(null, new Runnable() { + @Override + public void run() { + DBTManager.shutdownImpl(true); + } }, "DBTManager_ShutdownHook" ) ) ; + return null; + } } ) ; + } + + private static synchronized void shutdownImpl(final boolean _isJVMShuttingDown) { + isJVMShuttingDown = _isJVMShuttingDown; + if(DEBUG) { + System.err.println("DBTManager.shutdown() START: JVM Shutdown "+isJVMShuttingDown+", on thread "+Thread.currentThread().getName()); + } + synchronized(userShutdownHooks) { + final int cshCount = userShutdownHooks.size(); + for(int i=0; i < cshCount; i++) { + try { + if( DEBUG ) { + System.err.println("DBTManager.shutdown - userShutdownHook #"+(i+1)+"/"+cshCount); + } + userShutdownHooks.get(i).run(); + } catch(final Throwable t) { + System.err.println("DBTManager.shutdown: Caught "+t.getClass().getName()+" during userShutdownHook #"+(i+1)+"/"+cshCount); + if( DEBUG ) { + t.printStackTrace(); + } + } + } + userShutdownHooks.clear(); + } + if(DEBUG) { + System.err.println("DBTManager.shutdown(): Post userShutdownHook"); + } + + try { + final BluetoothManager mgmt = getBluetoothManager(); + mgmt.shutdown(); + } catch(final Throwable t) { + System.err.println("DBTManager.shutdown: Caught "+t.getClass().getName()+" during DBTManager.shutdown()"); + if( DEBUG ) { + t.printStackTrace(); + } + } + + if(DEBUG) { + System.err.println(Thread.currentThread().getName()+" - DBTManager.shutdown() END JVM Shutdown "+isJVMShuttingDown); + } + } + + /** Returns true if the JVM is shutting down, otherwise false. */ + public static final boolean isJVMShuttingDown() { return isJVMShuttingDown; } + + /** + * Add a shutdown hook to be performed at JVM shutdown before shutting down DBTManager instance. + * + * @param head if true add runnable at the start, otherwise at the end + * @param runnable runnable to be added. + */ + public static void addShutdownHook(final boolean head, final Runnable runnable) { + synchronized( userShutdownHooks ) { + if( !userShutdownHooks.contains( runnable ) ) { + if( head ) { + userShutdownHooks.add(0, runnable); + } else { + userShutdownHooks.add( runnable ); + } + } + } + } + private long nativeInstance; private static DBTManager inst; private final List<BluetoothAdapter> adapters = new ArrayList<BluetoothAdapter>(); @@ -147,6 +231,10 @@ public class DBTManager implements BluetoothManager @Override public void shutdown() { + for(final Iterator<BluetoothAdapter> ia= adapters.iterator(); ia.hasNext(); ) { + final BluetoothAdapter a = ia.next(); + a.close(); + } adapters.clear(); deleteImpl(); } diff --git a/java/jni/JNIMem.cxx b/java/jni/JNIMem.cxx index 992b1a95..eae05c4b 100644 --- a/java/jni/JNIMem.cxx +++ b/java/jni/JNIMem.cxx @@ -154,6 +154,11 @@ JNIGlobalRef::~JNIGlobalRef() { } } +void JNIGlobalRef::clear() { + DBG_PRINT("JNIGlobalRef::clear %p (nulled) -> null", object); + object = nullptr; +} + bool JNIGlobalRef::operator==(const JNIGlobalRef& rhs) const { if( &rhs == this ) { DBG_PRINT("JNIGlobalRef::== true: %p == %p (ptr)", object, rhs.object); diff --git a/java/jni/JNIMem.hpp b/java/jni/JNIMem.hpp index b7f5323b..fee3348b 100644 --- a/java/jni/JNIMem.hpp +++ b/java/jni/JNIMem.hpp @@ -93,6 +93,9 @@ public: /* Deletes the stored GlobalRef */ ~JNIGlobalRef(); + /** Clears the java reference, i.e. nulling it, without deleting the global reference via JNI. */ + void clear(); + /* Provides access to the stored GlobalRef as an jobject. */ jobject operator*() { return object; } diff --git a/java/jni/direct_bt/DBTAdapter.cxx b/java/jni/direct_bt/DBTAdapter.cxx index 4ee1297a..f4b87195 100644 --- a/java/jni/direct_bt/DBTAdapter.cxx +++ b/java/jni/direct_bt/DBTAdapter.cxx @@ -216,20 +216,27 @@ class AdapterStatusCallbackListener : public DBTAdapterStatusListener { fprintf(stderr, "%s\n", a.toString().c_str()); #endif (void)a; - - // Device(final long nativeInstance, final Adapter adptr, final String address, final String name) - const jstring addr = from_string_to_jstring(env, device->getAddressString()); - const jstring name = from_string_to_jstring(env, device->getName()); - if( java_exception_check(env, E_FILE_LINE) ) { return; } - jobject jDevice = env->NewObject(deviceClazzRef->getClass(), deviceClazzCtor, - (jlong)device.get(), adapterObjRef, addr, name, (jlong)timestamp); - if( java_exception_check(env, E_FILE_LINE) ) { return; } - JNIGlobalRef::check(jDevice, E_FILE_LINE); + jobject jdevice; std::shared_ptr<JavaAnonObj> jDeviceRef = device->getJavaObject(); - JavaGlobalObj::check(jDeviceRef, E_FILE_LINE); - + if( JavaGlobalObj::isValid(jDeviceRef) ) { + // Reuse Java instance + jdevice = JavaGlobalObj::GetObject(jDeviceRef); + } else { + // New Java instance + // Device(final long nativeInstance, final Adapter adptr, final String address, final String name) + const jstring addr = from_string_to_jstring(env, device->getAddressString()); + const jstring name = from_string_to_jstring(env, device->getName()); + if( java_exception_check(env, E_FILE_LINE) ) { return; } + jobject jDevice = env->NewObject(deviceClazzRef->getClass(), deviceClazzCtor, + (jlong)device.get(), adapterObjRef, addr, name, (jlong)timestamp); + if( java_exception_check(env, E_FILE_LINE) ) { return; } + JNIGlobalRef::check(jDevice, E_FILE_LINE); + std::shared_ptr<JavaAnonObj> jDeviceRef = device->getJavaObject(); + JavaGlobalObj::check(jDeviceRef, E_FILE_LINE); + jdevice = JavaGlobalObj::GetObject(jDeviceRef); + } env->CallVoidMethod(listenerObjRef->getObject(), mDeviceFound, - JavaGlobalObj::GetObject(adapterObjRef), JavaGlobalObj::GetObject(jDeviceRef), (jlong)timestamp); + JavaGlobalObj::GetObject(adapterObjRef), jdevice, (jlong)timestamp); if( java_exception_check(env, E_FILE_LINE) ) { return; } } catch(...) { rethrow_and_raise_java_exception(env); diff --git a/java/jni/direct_bt/DBTDevice.cxx b/java/jni/direct_bt/DBTDevice.cxx index d192ba9a..67538132 100644 --- a/java/jni/direct_bt/DBTDevice.cxx +++ b/java/jni/direct_bt/DBTDevice.cxx @@ -66,12 +66,29 @@ jboolean Java_direct_1bt_tinyb_DBTDevice_addStatusListener(JNIEnv *env, jobject return JNI_FALSE; } +jboolean Java_direct_1bt_tinyb_DBTDevice_removeStatusListener(JNIEnv *env, jobject obj, jobject statusListener) +{ + try { + DBTDevice *device = getInstance<DBTDevice>(env, obj); + JavaGlobalObj::check(device->getJavaObject(), E_FILE_LINE); + + DBTAdapter * adapter = const_cast<DBTAdapter *>( &device->getAdapter() ); + std::shared_ptr<JavaAnonObj> adapterObjRef = adapter->getJavaObject(); + JavaGlobalObj::check(adapterObjRef, E_FILE_LINE); + jobject jadapter = JavaGlobalObj::GetObject(adapterObjRef); + + return Java_direct_1bt_tinyb_DBTAdapter_removeStatusListener(env, jadapter, statusListener); + } catch(...) { + rethrow_and_raise_java_exception(env); + } + return JNI_FALSE; +} + void Java_direct_1bt_tinyb_DBTDevice_deleteImpl(JNIEnv *env, jobject obj) { try { DBTDevice *device = getInstance<DBTDevice>(env, obj); device->remove(); - delete device; } catch(...) { rethrow_and_raise_java_exception(env); } diff --git a/java/jni/direct_bt/DBTManager.cxx b/java/jni/direct_bt/DBTManager.cxx index b67afafe..00d9281a 100644 --- a/java/jni/direct_bt/DBTManager.cxx +++ b/java/jni/direct_bt/DBTManager.cxx @@ -56,9 +56,8 @@ void Java_direct_1bt_tinyb_DBTManager_deleteImpl(JNIEnv *env, jobject obj) { try { DBTManager *manager = getInstance<DBTManager>(env, obj); // special: static singleton - manager->setJavaObject(nullptr); manager->close(); - // delete manager; + manager->setJavaObject(nullptr); (void) manager; } catch(...) { rethrow_and_raise_java_exception(env); @@ -96,7 +95,7 @@ jobject Java_direct_1bt_tinyb_DBTManager_getDefaultAdapterImpl(JNIEnv *env, jobj std::shared_ptr<JavaAnonObj> jAdapterRef = adapter->getJavaObject(); JavaGlobalObj::check(jAdapterRef, E_FILE_LINE); - DBG_PRINT("Java_direct_1bt_tinyb_DBTManager_getDefaultAdapterImpl: New Adapter %s", adapter->toString().c_str()); + DBG_PRINT("Java_direct_1bt_tinyb_DBTManager_getDefaultAdapterImpl: New Adapter %p %s", adapter, adapter->toString().c_str()); return JavaGlobalObj::GetObject(jAdapterRef); } catch(...) { rethrow_and_raise_java_exception(env); @@ -138,7 +137,7 @@ jobject Java_direct_1bt_tinyb_DBTManager_getAdapterListImpl(JNIEnv *env, jobject std::shared_ptr<JavaAnonObj> jAdapterRef = adapter->getJavaObject(); JavaGlobalObj::check(jAdapterRef, E_FILE_LINE); - DBG_PRINT("Java_direct_1bt_tinyb_DBTManager_getAdapterListImpl: New Adapter %s", adapter->toString().c_str()); + DBG_PRINT("Java_direct_1bt_tinyb_DBTManager_getAdapterListImpl: New Adapter %p %s", adapter, adapter->toString().c_str()); return JavaGlobalObj::GetObject(jAdapterRef); }; return convert_vector_to_jobject<DBTAdapter>(env, adapters, _adapterClazzCtorArgs.c_str(), ctor_adapter); diff --git a/java/jni/direct_bt/DBTNativeDownlink.cxx b/java/jni/direct_bt/DBTNativeDownlink.cxx index 4aebef7e..78270664 100644 --- a/java/jni/direct_bt/DBTNativeDownlink.cxx +++ b/java/jni/direct_bt/DBTNativeDownlink.cxx @@ -43,7 +43,7 @@ void Java_direct_1bt_tinyb_DBTNativeDownlink_initNativeJavaObject(JNIEnv *env, j std::shared_ptr<JavaGlobalObj> jobjRef( new JavaGlobalObj(obj) ); javaUplink->setJavaObject( jobjRef ); JavaGlobalObj::check(javaUplink->getJavaObject(), E_FILE_LINE); - DBG_PRINT("Java_direct_1bt_tinyb_DBTNativeDownlink_initNativeJavaObject %s", javaUplink->toString().c_str()); + DBG_PRINT("Java_direct_1bt_tinyb_DBTNativeDownlink_initNativeJavaObject %p -> %s", javaUplink, javaUplink->toString().c_str()); } catch(...) { rethrow_and_raise_java_exception(env); } @@ -54,7 +54,7 @@ void Java_direct_1bt_tinyb_DBTNativeDownlink_clearNativeJavaObject(JNIEnv *env, (void)obj; try { JavaUplink *javaUplink = castInstance<JavaUplink>(nativeInstance); - DBG_PRINT("Java_direct_1bt_tinyb_DBTNativeDownlink_clearNativeJavaObject %s", javaUplink->toString().c_str()); + DBG_PRINT("Java_direct_1bt_tinyb_DBTNativeDownlink_clearNativeJavaObject %p -> %s", javaUplink, javaUplink->toString().c_str()); javaUplink->setJavaObject(nullptr); } catch(...) { rethrow_and_raise_java_exception(env); diff --git a/java/jni/direct_bt/helper_dbt.hpp b/java/jni/direct_bt/helper_dbt.hpp index 0264c795..5980fa56 100644 --- a/java/jni/direct_bt/helper_dbt.hpp +++ b/java/jni/direct_bt/helper_dbt.hpp @@ -49,6 +49,16 @@ namespace direct_bt { throw direct_bt::RuntimeException("JavaGlobalObj::check: Null object", file, line); } } + static bool isValid(const std::shared_ptr<JavaAnonObj> & shref) { + if( nullptr == shref ) { + return false; + } + const jobject obj = static_cast<const JavaGlobalObj*>(shref.get())->getObject(); + if( nullptr == obj ) { + return false; + } + return true; + } JavaGlobalObj(jobject obj) : javaObjectRef(obj) { } ~JavaGlobalObj() override { } @@ -57,6 +67,9 @@ namespace direct_bt { return "JavaGlobalObj["+uint64HexString(ref, true)+"]"; } + /** Clears the java reference, i.e. nulling it, without deleting the global reference via JNI. */ + void clear() override { javaObjectRef.clear(); } + JNIGlobalRef & getJavaObject() { return javaObjectRef; } /* Provides access to the stored GlobalRef as an jobject. */ diff --git a/src/direct_bt/DBTAdapter.cpp b/src/direct_bt/DBTAdapter.cpp index 8f1e6145..69de43c6 100644 --- a/src/direct_bt/DBTAdapter.cpp +++ b/src/direct_bt/DBTAdapter.cpp @@ -205,7 +205,7 @@ DBTAdapter::DBTAdapter(const int dev_id) } DBTAdapter::~DBTAdapter() { - DBG_PRINT("DBTAdapter::dtor: ... %s", toString().c_str()); + DBG_PRINT("DBTAdapter::dtor: ... %p %s", this, toString().c_str()); keepDiscoveringAlive = false; { int count; @@ -590,9 +590,15 @@ bool DBTAdapter::mgmtEvDeviceFoundCB(std::shared_ptr<MgmtEvent> e) { if( nullptr != dev ) { // // active shared device, but flushed from discovered devices + // - update device + // - issue deviceFound, allowing receivers to recognize the re-discovered device + // - issue deviceUpdate if data has changed, allowing receivers to act upon // - addDiscoveredDevice(dev); // re-add to discovered devices! EIRDataType updateMask = dev->update(ad_report); + addDiscoveredDevice(dev); // re-add to discovered devices! + for_each_idx_mtx(mtx_statusListenerList, statusListenerList, [&](std::shared_ptr<DBTAdapterStatusListener> &l) { + l->deviceFound(*this, dev, ad_report.getTimestamp()); + }); if( EIRDataType::NONE != updateMask ) { sendDeviceUpdated(dev, ad_report.getTimestamp(), updateMask); } diff --git a/src/direct_bt/DBTDevice.cpp b/src/direct_bt/DBTDevice.cpp index 983e97b8..d0900405 100644 --- a/src/direct_bt/DBTDevice.cpp +++ b/src/direct_bt/DBTDevice.cpp @@ -32,7 +32,7 @@ #include <algorithm> -// #define VERBOSE_ON 1 +#define VERBOSE_ON 1 #include <dbt_debug.hpp> #include "HCIComm.hpp" @@ -55,6 +55,7 @@ DBTDevice::DBTDevice(DBTAdapter & a, EInfoReport const & r) } DBTDevice::~DBTDevice() { + DBG_PRINT("DBTDevice::dtor: ... %p %s", this, toString().c_str()); remove(); services.clear(); msd = nullptr; @@ -321,7 +322,7 @@ void DBTDevice::disconnect(const uint8_t reason) { const uint16_t _connHandle = connHandle; connHandle = 0; if( !session->hciComm.disconnect(_connHandle, reason) ) { - DBG_PRINT("DBTDevice::disconnect: handle 0x%X, errno %d %s", _leConnHandle, errno, strerror(errno)); + DBG_PRINT("DBTDevice::disconnect: handle 0x%X, errno %d %s", _connHandle, errno, strerror(errno)); } } |