26 #include "jau_direct_bt_DBTAdapter.h"
53 static const std::string
_adapterSettingsChangedMethodArgs(
"(Lorg/direct_bt/BTAdapter;Lorg/direct_bt/AdapterSettings;Lorg/direct_bt/AdapterSettings;Lorg/direct_bt/AdapterSettings;J)V");
82 static std::atomic<int> iname_next;
84 BTDevice const *
const deviceMatchRef;
87 std::shared_ptr<jau::JavaAnon> adapterObjRef;
89 jmethodID adapterSettingsClazzCtor;
91 jmethodID eirDataTypeSetClazzCtor;
93 jmethodID hciStatusCodeClazzGet;
95 jmethodID scanTypeClazzGet;
97 jmethodID pairingModeClazzGet;
99 jmethodID pairingStateClazzGet;
102 jmethodID deviceClazzCtor;
103 jfieldID deviceClazzTSLastDiscoveryField;
104 jfieldID deviceClazzTSLastUpdateField;
105 jfieldID deviceClazzConnectionHandleField;
106 jmethodID mAdapterSettingsChanged =
nullptr;
107 jmethodID mDiscoveringChanged =
nullptr;
108 jmethodID mDeviceFound =
nullptr;
109 jmethodID mDeviceUpdated =
nullptr;
110 jmethodID mDeviceConnected=
nullptr;
111 jmethodID mDevicePairingState=
nullptr;
112 jmethodID mDeviceReady =
nullptr;
113 jmethodID mDeviceDisconnected =
nullptr;
127 jclass listenerClazz, jobject statusListenerObj, jmethodID statusListenerNotifyDeleted,
129 : iname(iname_next.fetch_add(1)), deviceMatchRef(_deviceMatchRef),
130 listenerObjRef(statusListenerObj, statusListenerNotifyDeleted)
139 if(
nullptr == adapterSettingsClazz ) {
142 adapterSettingsClazzRef =
JNIGlobalRef(adapterSettingsClazz);
143 env->DeleteLocalRef(adapterSettingsClazz);
147 if(
nullptr == adapterSettingsClazzCtor ) {
155 if(
nullptr == eirDataTypeSetClazz ) {
158 eirDataTypeSetClazzRef =
JNIGlobalRef(eirDataTypeSetClazz);
159 env->DeleteLocalRef(eirDataTypeSetClazz);
163 if(
nullptr == eirDataTypeSetClazzCtor ) {
171 if(
nullptr == hciErrorCodeClazz ) {
174 hciStatusCodeClazzRef =
JNIGlobalRef(hciErrorCodeClazz);
175 env->DeleteLocalRef(hciErrorCodeClazz);
179 if(
nullptr == hciStatusCodeClazzGet ) {
187 if(
nullptr == scanTypeClazz ) {
191 env->DeleteLocalRef(scanTypeClazz);
195 if(
nullptr == scanTypeClazzGet ) {
203 if(
nullptr == pairingModeClazz ) {
207 env->DeleteLocalRef(pairingModeClazz);
211 if(
nullptr == pairingModeClazzGet ) {
219 if(
nullptr == pairingStateClazz ) {
223 env->DeleteLocalRef(pairingStateClazz);
227 if(
nullptr == pairingStateClazzGet ) {
235 if(
nullptr == deviceClazz ) {
239 env->DeleteLocalRef(deviceClazz);
243 if(
nullptr == deviceClazzCtor ) {
246 deviceClazzTSLastDiscoveryField = env->GetFieldID(deviceClazzRef.
getClass(),
"ts_last_discovery",
"J");
248 if(
nullptr == deviceClazzTSLastDiscoveryField ) {
251 deviceClazzTSLastUpdateField = env->GetFieldID(deviceClazzRef.
getClass(),
"ts_last_update",
"J");
253 if(
nullptr == deviceClazzTSLastUpdateField ) {
256 deviceClazzConnectionHandleField = env->GetFieldID(deviceClazzRef.
getClass(),
"hciConnHandle",
"S");
258 if(
nullptr == deviceClazzConnectionHandleField ) {
264 if(
nullptr == mAdapterSettingsChanged ) {
269 if(
nullptr == mDiscoveringChanged ) {
274 if(
nullptr == mDeviceFound ) {
279 if(
nullptr == mDeviceUpdated ) {
284 if(
nullptr == mDeviceConnected ) {
289 if(
nullptr == mDevicePairingState ) {
294 if(
nullptr == mDeviceReady ) {
299 if(
nullptr == mDeviceDisconnected ) {
305 if(
nullptr == deviceMatchRef ) {
308 return device == *deviceMatchRef;
312 const AdapterSetting changedmask,
const uint64_t timestamp)
override {
315 jobject adapterSettingOld = env->NewObject(adapterSettingsClazzRef.
getClass(), adapterSettingsClazzCtor, (jint)oldmask);
319 jobject adapterSettingNew = env->NewObject(adapterSettingsClazzRef.
getClass(), adapterSettingsClazzCtor, (jint)newmask);
323 jobject adapterSettingChanged = env->NewObject(adapterSettingsClazzRef.
getClass(), adapterSettingsClazzCtor, (jint)changedmask);
327 env->CallVoidMethod(listenerObjRef.
getObject(), mAdapterSettingsChanged,
330 env->DeleteLocalRef(adapterSettingOld);
331 env->DeleteLocalRef(adapterSettingNew);
332 env->DeleteLocalRef(adapterSettingChanged);
339 jobject jcurrentMeta = env->CallStaticObjectMethod(scanTypeClazzRef.
getClass(), scanTypeClazzGet, (jbyte)
number(currentMeta));
343 jobject jchangedType = env->CallStaticObjectMethod(scanTypeClazzRef.
getClass(), scanTypeClazzGet, (jbyte)
number(changedType));
348 jcurrentMeta, jchangedType, (jboolean)changedEnabled, (jboolean)keepAlive, (jlong)timestamp);
354 jobject newJavaBTDevice(JNIEnv *env, std::shared_ptr<BTDevice> device,
const uint64_t timestamp) {
358 jbyteArray jaddr = env->NewByteArray(
sizeof(addr));
359 env->SetByteArrayRegion(jaddr, 0,
sizeof(addr), (
const jbyte*)(addr.
b));
363 jobject tmp_jdevice = env->NewObject(deviceClazzRef.
getClass(), deviceClazzCtor,
368 std::shared_ptr<jau::JavaAnon> jDeviceRef1 = device->
getJavaObject();
371 env->DeleteLocalRef(jaddr);
372 env->DeleteLocalRef(name);
373 env->DeleteLocalRef(tmp_jdevice);
379 bool deviceFound(std::shared_ptr<BTDevice> device,
const uint64_t timestamp)
override {
382 std::shared_ptr<jau::JavaAnon> jDeviceRef0 = device->
getJavaObject();
387 jdevice = newJavaBTDevice(env, device, timestamp);
391 jboolean res = env->CallBooleanMethod(listenerObjRef.
getObject(), mDeviceFound, jdevice, (jlong)timestamp);
393 return JNI_TRUE == res;
397 std::shared_ptr<jau::JavaAnon> jDeviceRef = device->
getJavaObject();
405 jobject eirDataTypeSet = env->NewObject(eirDataTypeSetClazzRef.
getClass(), eirDataTypeSetClazzCtor, (jint)updateMask);
411 env->DeleteLocalRef(eirDataTypeSet);
414 void deviceConnected(std::shared_ptr<BTDevice> device,
const uint16_t handle,
const uint64_t timestamp)
override {
418 std::shared_ptr<jau::JavaAnon> jDeviceRef0 = device->
getJavaObject();
423 jdevice = newJavaBTDevice(env, device, timestamp);
425 env->SetShortField(jdevice, deviceClazzConnectionHandleField, (jshort)handle);
429 env->SetLongField(jdevice, deviceClazzTSLastUpdateField, (jlong)timestamp);
432 env->CallVoidMethod(listenerObjRef.
getObject(), mDeviceConnected, jdevice, (jshort)handle, (jlong)timestamp);
436 std::shared_ptr<jau::JavaAnon> jDeviceRef = device->
getJavaObject();
443 env->SetLongField(jdevice, deviceClazzTSLastUpdateField, (jlong)timestamp);
446 jobject jstate = env->CallStaticObjectMethod(pairingStateClazzRef.
getClass(), pairingStateClazzGet,
static_cast<uint8_t
>(state));
450 jobject jmode = env->CallStaticObjectMethod(pairingModeClazzRef.
getClass(), pairingModeClazzGet,
static_cast<uint8_t
>(mode));
454 env->CallVoidMethod(listenerObjRef.
getObject(), mDevicePairingState, jdevice, jstate, jmode, (jlong)timestamp);
457 void deviceReady(std::shared_ptr<BTDevice> device,
const uint64_t timestamp)
override {
458 std::shared_ptr<jau::JavaAnon> jDeviceRef = device->
getJavaObject();
465 env->SetLongField(jdevice, deviceClazzTSLastUpdateField, (jlong)timestamp);
468 env->CallVoidMethod(listenerObjRef.
getObject(), mDeviceReady, jdevice, (jlong)timestamp);
472 std::shared_ptr<jau::JavaAnon> jDeviceRef = device->
getJavaObject();
479 env->SetLongField(jdevice, deviceClazzTSLastUpdateField, (jlong)timestamp);
482 jobject hciErrorCode = env->CallStaticObjectMethod(hciStatusCodeClazzRef.
getClass(), hciStatusCodeClazzGet, (jbyte)
static_cast<uint8_t
>(reason));
486 env->SetShortField(jdevice, deviceClazzConnectionHandleField, (jshort)0);
489 env->CallVoidMethod(listenerObjRef.
getObject(), mDeviceDisconnected, jdevice, hciErrorCode, (jshort)handle, (jlong)timestamp);
493 std::atomic<int> JNIAdapterStatusListener::iname_next(0);
498 if(
nullptr == statusListener ) {
503 if(
nullptr != pre ) {
508 BTAdapter *adapter = jau::getJavaUplinkObject<BTAdapter>(env, obj);
511 BTDevice * deviceOwnerAndMatchRef =
nullptr;
512 if(
nullptr != jdeviceOwnerAndMatch ) {
513 deviceOwnerAndMatchRef = jau::getJavaUplinkObject<BTDevice>(env, jdeviceOwnerAndMatch);
519 if(
nullptr == listenerClazz ) {
522 jmethodID mStatusListenerNotifyDeleted =
jau::search_method(env, listenerClazz,
"notifyDeleted",
"()V",
false);
524 if(
nullptr == mStatusListenerNotifyDeleted ) {
528 std::shared_ptr<AdapterStatusListener> l =
530 listenerClazz, statusListener, mStatusListenerNotifyDeleted, deviceOwnerAndMatchRef) );
532 env->DeleteLocalRef(listenerClazz);
536 if(
nullptr != deviceOwnerAndMatchRef ) {
545 ERR_PRINT(
"JNIAdapterStatusListener::addStatusListener: FAILED: %s", l->
toString().c_str());
556 if(
nullptr == statusListener ) {
560 if(
nullptr == pre ) {
561 DBG_PRINT(
"JNIAdapterStatusListener::removeStatusListener: statusListener's nativeInstance is null, not in use");
566 BTAdapter *adapter = jau::getJavaUplinkObject<BTAdapter>(env, obj);
570 WARN_PRINT(
"Failed to remove statusListener with nativeInstance: %p at %s", pre, adapter->
toString().c_str());
575 if(
nullptr != post ) {
576 ERR_PRINT(
"JNIAdapterStatusListener::removeStatusListener: statusListener's nativeInstance not null post native removal");
589 BTAdapter *adapter = jau::getJavaUplinkObject<BTAdapter>(env, obj);
592 return adapter->removeAllStatusListener();
601 BTAdapter *adapter = jau::getJavaUplinkObject<BTAdapter>(env, obj);
604 if(
nullptr == jaddress ) {
607 const size_t address_size = env->GetArrayLength(jaddress);
608 if(
sizeof(
EUI48) > address_size ) {
612 uint8_t * address_ptr = criticalArray.
get(jaddress, criticalArray.Mode::NO_UPDATE_AND_RELEASE);
613 if( NULL == address_ptr ) {
616 const EUI48& address = *
reinterpret_cast<EUI48 *
>(address_ptr);
626 jbyteArray jaddress, jbyte jaddressType,
int jctype,
627 jshort min_interval, jshort max_interval,
628 jshort latency, jshort timeout) {
630 BTAdapter *adapter = jau::getJavaUplinkObject<BTAdapter>(env, obj);
633 if(
nullptr == jaddress ) {
636 const size_t address_size = env->GetArrayLength(jaddress);
637 if(
sizeof(
EUI48) > address_size ) {
641 uint8_t * address_ptr = criticalArray.
get(jaddress, criticalArray.Mode::NO_UPDATE_AND_RELEASE);
642 if( NULL == address_ptr ) {
645 const EUI48& address = *
reinterpret_cast<EUI48 *
>(address_ptr);
649 return adapter->
addDeviceToWhitelist(addressAndType, ctype, (uint16_t)min_interval, (uint16_t)max_interval, (uint16_t)latency, (uint16_t)timeout);
656 jbyteArray jaddress, jbyte jaddressType,
int jctype) {
658 BTAdapter *adapter = jau::getJavaUplinkObject<BTAdapter>(env, obj);
661 if(
nullptr == jaddress ) {
664 const size_t address_size = env->GetArrayLength(jaddress);
665 if(
sizeof(
EUI48) > address_size ) {
669 uint8_t * address_ptr = criticalArray.
get(jaddress, criticalArray.Mode::NO_UPDATE_AND_RELEASE);
670 if( NULL == address_ptr ) {
673 const EUI48& address = *
reinterpret_cast<EUI48 *
>(address_ptr);
685 BTAdapter *adapter = jau::getJavaUplinkObject<BTAdapter>(env, obj);
688 if(
nullptr == jaddress ) {
691 const size_t address_size = env->GetArrayLength(jaddress);
692 if(
sizeof(
EUI48) > address_size ) {
696 uint8_t * address_ptr = criticalArray.
get(jaddress, criticalArray.Mode::NO_UPDATE_AND_RELEASE);
697 if( NULL == address_ptr ) {
700 const EUI48& address = *
reinterpret_cast<EUI48 *
>(address_ptr);
712 BTAdapter *nativePtr = jau::getJavaUplinkObject<BTAdapter>(env, obj);
725 BTAdapter *adapter = jau::castInstance<BTAdapter>(nativeInstance);
726 DBG_PRINT(
"Java_jau_direct_1bt_DBTAdapter_deleteImpl (close only) %s", adapter->
toString().c_str());
738 BTAdapter *adapter = jau::getJavaUplinkObject<BTAdapter>(env, obj);
749 BTAdapter *adapter = jau::getJavaUplinkObject<BTAdapter>(env, obj);
760 BTAdapter *adapter = jau::getJavaUplinkObject<BTAdapter>(env, obj);
773 BTAdapter *adapter = jau::getJavaUplinkObject<BTAdapter>(env, obj);
784 BTAdapter *adapter = jau::getJavaUplinkObject<BTAdapter>(env, obj);
795 BTAdapter *adapter = jau::getJavaUplinkObject<BTAdapter>(env, obj);
807 BTAdapter *adapter = jau::getJavaUplinkObject<BTAdapter>(env, obj);
818 BTAdapter *adapter = jau::getJavaUplinkObject<BTAdapter>(env, obj);
821 if(
nullptr == jaddress ) {
824 const size_t address_size = env->GetArrayLength(jaddress);
825 if(
sizeof(
EUI48) > address_size ) {
829 uint8_t * address_ptr = criticalArray.
get(jaddress, criticalArray.Mode::NO_UPDATE_AND_RELEASE);
830 if( NULL == address_ptr ) {
833 const EUI48& address = *
reinterpret_cast<EUI48 *
>(address_ptr);
849 BTAdapter *adapter = jau::getJavaUplinkObject<BTAdapter>(env, obj);
851 return adapter->
setPowered(JNI_TRUE == value ?
true :
false) ? JNI_TRUE : JNI_FALSE;
860 BTAdapter *adapter = jau::getJavaUplinkObject<BTAdapter>(env, obj);
863 return (jbyte)
number(res);
872 BTAdapter *adapter = jau::getJavaUplinkObject<BTAdapter>(env, obj);
883 BTAdapter *adapter = jau::getJavaUplinkObject<BTAdapter>(env, obj);
894 BTAdapter *adapter = jau::getJavaUplinkObject<BTAdapter>(env, obj);
896 return adapter->
setDiscoverable(JNI_TRUE == value ?
true :
false) ? JNI_TRUE : JNI_FALSE;
905 BTAdapter *adapter = jau::getJavaUplinkObject<BTAdapter>(env, obj);
908 if(
nullptr == jaddress ) {
911 const size_t address_size = env->GetArrayLength(jaddress);
912 if(
sizeof(
EUI48) > address_size ) {
916 uint8_t * address_ptr = criticalArray.
get(jaddress, criticalArray.Mode::NO_UPDATE_AND_RELEASE);
917 if( NULL == address_ptr ) {
920 const EUI48& address = *
reinterpret_cast<EUI48 *
>(address_ptr);
923 std::shared_ptr<BTDevice> device = adapter->
findSharedDevice(address, addressType);
924 if(
nullptr == device ) {
927 if(
nullptr != device ) {
932 std::shared_ptr<jau::JavaAnon> jDeviceRef = device->
getJavaObject();
946 BTAdapter *adapter = jau::getJavaUplinkObject<BTAdapter>(env, obj);
948 return adapter->
setBondable(JNI_TRUE == value ?
true :
false) ? JNI_TRUE : JNI_FALSE;
957 BTAdapter *adapter = jau::getJavaUplinkObject<BTAdapter>(env, obj);