summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorSven Gothel <[email protected]>2020-05-12 06:39:36 +0200
committerSven Gothel <[email protected]>2020-05-12 06:39:36 +0200
commitd198176d2fbe5c88cf81ffb647abced753af52c2 (patch)
tree6d41698d308520adf7fd743e718724343e48292c
parent604e03053942521c1e104b0c473864ff4139b939 (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.hpp12
-rw-r--r--examples/java/ScannerTinyB01.java18
-rw-r--r--java/direct_bt/tinyb/DBTAdapter.java14
-rw-r--r--java/direct_bt/tinyb/DBTDevice.java4
-rw-r--r--java/direct_bt/tinyb/DBTManager.java88
-rw-r--r--java/jni/JNIMem.cxx5
-rw-r--r--java/jni/JNIMem.hpp3
-rw-r--r--java/jni/direct_bt/DBTAdapter.cxx31
-rw-r--r--java/jni/direct_bt/DBTDevice.cxx19
-rw-r--r--java/jni/direct_bt/DBTManager.cxx7
-rw-r--r--java/jni/direct_bt/DBTNativeDownlink.cxx4
-rw-r--r--java/jni/direct_bt/helper_dbt.hpp13
-rw-r--r--src/direct_bt/DBTAdapter.cpp10
-rw-r--r--src/direct_bt/DBTDevice.cpp5
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));
}
}