Direct-BT  2.3.1
Direct-BT - Direct Bluetooth Programming.
DBTManager.cxx
Go to the documentation of this file.
1 /*
2  * Author: Sven Gothel <sgothel@jausoft.com>
3  * Copyright (c) 2020 Gothel Software e.K.
4  * Copyright (c) 2020 ZAFENA AB
5  *
6  * Permission is hereby granted, free of charge, to any person obtaining
7  * a copy of this software and associated documentation files (the
8  * "Software"), to deal in the Software without restriction, including
9  * without limitation the rights to use, copy, modify, merge, publish,
10  * distribute, sublicense, and/or sell copies of the Software, and to
11  * permit persons to whom the Software is furnished to do so, subject to
12  * the following conditions:
13  *
14  * The above copyright notice and this permission notice shall be
15  * included in all copies or substantial portions of the Software.
16  *
17  * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
18  * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
19  * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
20  * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
21  * LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
22  * OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
23  * WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
24  */
25 
26 #include "jau_direct_bt_DBTManager.h"
27 
28 // #define VERBOSE_ON 1
29 #include <jau/debug.hpp>
30 
31 #include "helper_base.hpp"
32 #include "helper_dbt.hpp"
33 
34 #include "direct_bt/BTDevice.hpp"
35 #include "direct_bt/BTAdapter.hpp"
36 #include "direct_bt/BTManager.hpp"
37 
38 using namespace direct_bt;
39 using namespace jau;
40 
41 static const std::string _removeAdapterCBMethodName("removeAdapterCB");
42 static const std::string _removeAdapterCBMethodArgs("(II)V");
43 static const std::string _updatedAdapterCBMethodName("updatedAdapterCB");
44 static const std::string _updatedAdapterCBMethodArgs("(II)V");
45 
49  jmethodID mid;
50 
51  BooleanMgmtCBContext(MgmtEvent::Opcode opc_, JNIGlobalRef jmgmtRef_, jmethodID mid_)
52  : opc(opc_), jmgmtRef(jmgmtRef_), mid(mid_) { }
53 
54  bool operator==(const BooleanMgmtCBContext& rhs) const
55  {
56  if( &rhs == this ) {
57  return true;
58  }
59  return rhs.opc == opc &&
60  rhs.jmgmtRef == jmgmtRef;
61  }
62 
63  bool operator!=(const BooleanMgmtCBContext& rhs) const
64  { return !( *this == rhs ); }
65 
66 };
67 typedef std::shared_ptr<BooleanMgmtCBContext> BooleanMgmtCBContextRef;
68 
69 static void _addMgmtCBOnce(JNIEnv *env, BTManager & mgmt, JNIGlobalRef jmgmtRef, MgmtEvent::Opcode opc,
70  const std::string &jmethodName, const std::string &jmethodArgs)
71 {
72  try {
73  bool(*nativeCallback)(BooleanMgmtCBContextRef&, const MgmtEvent&) =
74  [](BooleanMgmtCBContextRef& ctx_ref, const MgmtEvent& e)->bool {
75  JNIEnv *env_ = *jni_env;
76  const int dev_id = e.getDevID();
77 
78  if( MgmtEvent::Opcode::INDEX_REMOVED == ctx_ref->opc ) {
79  env_->CallVoidMethod(*(ctx_ref->jmgmtRef), ctx_ref->mid, dev_id, ctx_ref->opc); // remove
80  } else if( MgmtEvent::Opcode::INDEX_ADDED == ctx_ref->opc ) {
81  env_->CallVoidMethod(*(ctx_ref->jmgmtRef), ctx_ref->mid, dev_id, ctx_ref->opc); // updated
82  } else if( MgmtEvent::Opcode::NEW_SETTINGS == ctx_ref->opc ) {
83  const MgmtEvtNewSettings &event = *static_cast<const MgmtEvtNewSettings *>(&e);
84  if( isAdapterSettingBitSet(event.getSettings(), AdapterSetting::POWERED) ) {
85  // probably newly POWERED on
86  env_->CallVoidMethod(*(ctx_ref->jmgmtRef), ctx_ref->mid, dev_id, ctx_ref->opc); // updated
87  }
88  }
89  return true;
90  };
91 
92 
93  jclass mgmtClazz = jau::search_class(env, jmgmtRef.getObject());
95  if( nullptr == mgmtClazz ) {
96  throw jau::InternalError("BTManager not found", E_FILE_LINE);
97  }
98  jmethodID mid = jau::search_method(env, mgmtClazz, jmethodName.c_str(), jmethodArgs.c_str(), false);
100  if( nullptr == mid ) {
101  throw jau::InternalError("BTManager has no "+jmethodName+"."+jmethodArgs+" method, for "+mgmt.toString(), E_FILE_LINE);
102  }
103 
104  // move BooleanDeviceCBContextRef into CaptureInvocationFunc and operator== includes javaCallback comparison
105  FunctionDef<bool, const MgmtEvent&> funcDef = bindCaptureFunc(std::make_shared<BooleanMgmtCBContext>(opc, jmgmtRef, mid), nativeCallback);
106  mgmt.addMgmtEventCallback(-1, opc, funcDef);
107  } catch(...) {
109  }
110 }
111 
112 void Java_jau_direct_1bt_DBTManager_initImpl(JNIEnv *env, jobject obj, jboolean unifyUUID128Bit, jint jbtMode)
113 {
114  directBTJNISettings.setUnifyUUID128Bit(unifyUUID128Bit);
115  try {
116  BTMode btMode = static_cast<BTMode>(jbtMode);
117  BTManager *manager = &BTManager::get(btMode); // special: static singleton
118  setInstance<BTManager>(env, obj, manager);
120  manager->setJavaObject( std::shared_ptr<JavaAnon>( new JavaGlobalObj(obj, nullptr) ) );
121  JavaGlobalObj::check(manager->getJavaObject(), E_FILE_LINE);
122 
123  JNIGlobalRef jmgmtRef = JavaGlobalObj::GetJavaObject(manager->getJavaObject());
127  DBG_PRINT("Java_jau_direct_1bt_DBTManager_init: Manager %s", manager->toString().c_str());
128  } catch(...) {
130  }
131 }
132 
133 void Java_jau_direct_1bt_DBTManager_deleteImpl(JNIEnv *env, jobject obj, jlong nativeInstance)
134 {
135  (void)obj;
136  try {
137  BTManager *manager = castInstance<BTManager>(nativeInstance); // special: static singleton
138  manager->close();
139  manager->setJavaObject();
140  (void) manager;
141  } catch(...) {
143  }
144 }
145 
146 static const std::string _adapterClazzCtorArgs("(J[BBLjava/lang/String;I)V");
147 static jobject _createJavaAdapter(JNIEnv *env_, jclass clazz, jmethodID clazz_ctor, BTAdapter* adapter) {
148  // prepare adapter ctor
149  const EUI48 addr = adapter->getAddressAndType().address;
150  jbyteArray jaddr = env_->NewByteArray(sizeof(addr));
151  env_->SetByteArrayRegion(jaddr, 0, sizeof(addr), (const jbyte*)(addr.b));
153  const jstring name = from_string_to_jstring(env_, adapter->getName());
155  jobject jAdapter = env_->NewObject(clazz, clazz_ctor, (jlong)adapter, jaddr, adapter->getAddressAndType().type, name, adapter->dev_id);
157  JNIGlobalRef::check(jAdapter, E_FILE_LINE);
158  std::shared_ptr<JavaAnon> jAdapterRef = adapter->getJavaObject(); // GlobalRef
159  JavaGlobalObj::check(jAdapterRef, E_FILE_LINE);
160  env_->DeleteLocalRef(jaddr);
161  env_->DeleteLocalRef(name);
162  env_->DeleteLocalRef(jAdapter);
163 
164  DBG_PRINT("Java_jau_direct_1bt_DBTManager_createJavaAdapter: New Adapter %p %s", adapter, adapter->toString().c_str());
165  return JavaGlobalObj::GetObject(jAdapterRef);
166 };
167 
168 jobject Java_jau_direct_1bt_DBTManager_getAdapterListImpl(JNIEnv *env, jobject obj)
169 {
170  try {
171  BTManager *manager = getInstance<BTManager>(env, obj);
172  DBG_PRINT("Java_jau_direct_1bt_DBTManager_getAdapterListImpl: Manager %s", manager->toString().c_str());
173 
175  return convert_vector_sharedptr_to_jarraylist<jau::darray<std::shared_ptr<BTAdapter>>, BTAdapter>(
176  env, adapters, _adapterClazzCtorArgs.c_str(), _createJavaAdapter);
177  } catch(...) {
179  }
180  return nullptr;
181 }
182 
183 jobject Java_jau_direct_1bt_DBTManager_getAdapterImpl(JNIEnv *env, jobject obj, jint dev_id)
184 {
185  try {
186  BTManager *manager = getInstance<BTManager>(env, obj);
187 
188  std::shared_ptr<BTAdapter> adapter = manager->getAdapter(dev_id);
189  if( nullptr == adapter ) {
190  ERR_PRINT("BTManager::getAdapterImpl: Adapter dev_id %d: Not found", dev_id);
191  return nullptr;
192  }
193  DBG_PRINT("BTManager::getAdapterImpl: Adapter dev_id %d: %s", dev_id, adapter->toString().c_str());
194 
195  return jau::convert_instance_to_jobject<BTAdapter>(env, adapter.get(), _adapterClazzCtorArgs.c_str(), _createJavaAdapter);
196  } catch(...) {
198  }
199  return nullptr;
200 }
direct_bt::BTAdapter::getAddressAndType
BDAddressAndType const & getAddressAndType() const noexcept
Returns the adapter's public BDAddressAndType.
Definition: BTAdapter.hpp:497
direct_bt::MgmtEvtNewSettings
uint32_t settings
Definition: MgmtTypes.hpp:1371
BooleanMgmtCBContext::jmgmtRef
JNIGlobalRef jmgmtRef
Definition: DBTManager.cxx:48
_updatedAdapterCBMethodArgs
static const std::string _updatedAdapterCBMethodArgs("(II)V")
jau::bindCaptureFunc
jau::FunctionDef< R, A... > bindCaptureFunc(const I &data, R(*func)(I &, A...), bool dataIsIdentity=true) noexcept
const I& data will be copied into the InvocationFunc<..> specialization and hence captured by copy.
Definition: function_def.hpp:380
BTManager.hpp
jau::from_string_to_jstring
jstring from_string_to_jstring(JNIEnv *env, const std::string &str)
helper_dbt.hpp
helper_base.hpp
direct_bt
Definition: ATTPDUTypes.hpp:171
JNIGlobalRef::getObject
jobject getObject() const noexcept
Definition: jni_mem.hpp:108
jau::InternalError
Definition: basic_types.hpp:93
direct_bt::MgmtEvent::Opcode
Opcode
Definition: MgmtTypes.hpp:1085
JNIGlobalRef
Definition: jni_mem.hpp:75
_createJavaAdapter
static jobject _createJavaAdapter(JNIEnv *env_, jclass clazz, jmethodID clazz_ctor, BTAdapter *adapter)
Definition: DBTManager.cxx:147
direct_bt::MgmtEvent::Opcode::INDEX_ADDED
@ INDEX_ADDED
jau
Definition: basic_algos.hpp:34
BooleanMgmtCBContext::mid
jmethodID mid
Definition: DBTManager.cxx:49
_updatedAdapterCBMethodName
static const std::string _updatedAdapterCBMethodName("updatedAdapterCB")
jau::search_class
jclass search_class(JNIEnv *env, const char *clazz_name)
direct_bt::BTManager::close
void close() noexcept
Definition: BTManager.cpp:538
direct_bt::BTManager::toString
std::string toString() const noexcept override
Definition: BTManager.hpp:353
jau::java_exception_check_and_throw
void java_exception_check_and_throw(JNIEnv *env, const char *file, int line)
Throws a C++ exception if a java exception occurred, otherwise do nothing.
Java_jau_direct_1bt_DBTManager_deleteImpl
void Java_jau_direct_1bt_DBTManager_deleteImpl(JNIEnv *env, jobject obj, jlong nativeInstance)
Definition: DBTManager.cxx:133
direct_bt::DirectBTJNISettings::setUnifyUUID128Bit
void setUnifyUUID128Bit(bool v)
Definition: helper_dbt.hpp:48
jau::FunctionDef< bool, const MgmtEvent & >
direct_bt::MgmtEvent
uint16_t opcode, uint16_t dev-id, uint16_t param_size
Definition: MgmtTypes.hpp:1083
jni_env
thread_local JNIEnvContainer jni_env
E_FILE_LINE
#define E_FILE_LINE
Definition: basic_types.hpp:64
direct_bt::directBTJNISettings
DirectBTJNISettings directBTJNISettings
Definition: helper_dbt.cxx:35
jau::darray
Implementation of a dynamic linear array storage, aka vector.
Definition: darray.hpp:102
jau::search_method
jmethodID search_method(JNIEnv *env, jclass clazz, const char *method_name, const char *prototype, bool is_static)
BTAdapter.hpp
direct_bt::BDAddressAndType::type
BDAddressType type
Definition: BTAddress.hpp:429
direct_bt::BTManager::getAdapters
jau::darray< std::shared_ptr< BTAdapter > > getAdapters()
Returns a list of currently added DBTAdapter.
Definition: BTManager.hpp:367
direct_bt::MgmtMsg::getDevID
static uint16_t getDevID(const uint8_t *data)
Definition: MgmtTypes.hpp:320
direct_bt::BTAdapter::toString
std::string toString() const noexcept override
Definition: BTAdapter.hpp:784
direct_bt::MgmtEvent::Opcode::INDEX_REMOVED
@ INDEX_REMOVED
Java_jau_direct_1bt_DBTManager_getAdapterListImpl
jobject Java_jau_direct_1bt_DBTManager_getAdapterListImpl(JNIEnv *env, jobject obj)
Definition: DBTManager.cxx:168
JNIGlobalRef::check
static void check(jobject object, const char *file, int line)
Definition: jni_mem.hpp:80
direct_bt::BTManager::get
static BTManager & get(const BTMode defaultBTMode=BTMode::NONE)
Retrieves the singleton instance.
Definition: BTManager.hpp:320
direct_bt::BTManager
A thread safe singleton handler of the Linux Kernel's BlueZ manager control channel.
Definition: BTManager.hpp:201
debug.hpp
rethrow_and_raise_java_exception
#define rethrow_and_raise_java_exception(E)
Re-throw current exception and raise respective java exception using any matching function above.
Definition: helper_base.hpp:55
BooleanMgmtCBContextRef
std::shared_ptr< BooleanMgmtCBContext > BooleanMgmtCBContextRef
Definition: DBTManager.cxx:67
jau::JavaGlobalObj
Implementation for JavaAnon, by simply wrapping a JNIGlobalRef instance.
Definition: helper_jni.hpp:136
direct_bt::BTAdapter
BTAdapter represents one Bluetooth Controller.
Definition: BTAdapter.hpp:250
_removeAdapterCBMethodName
static const std::string _removeAdapterCBMethodName("removeAdapterCB")
direct_bt::EUI48
A packed 48 bit EUI-48 identifier, formerly known as MAC-48 or simply network device MAC address (Med...
Definition: BTAddress.hpp:388
direct_bt::BDAddressAndType::address
EUI48 address
Definition: BTAddress.hpp:428
ERR_PRINT
#define ERR_PRINT(...)
Use for unconditional error messages, prefix '[elapsed_time] Error @ FILE:LINE: '.
Definition: debug.hpp:132
direct_bt::EUI48::b
uint8_t b[6]
Definition: BTAddress.hpp:388
BooleanMgmtCBContext::operator==
bool operator==(const BooleanMgmtCBContext &rhs) const
Definition: DBTManager.cxx:54
_adapterClazzCtorArgs
static const std::string _adapterClazzCtorArgs("(J[BBLjava/lang/String;I)V")
BooleanMgmtCBContext::BooleanMgmtCBContext
BooleanMgmtCBContext(MgmtEvent::Opcode opc_, JNIGlobalRef jmgmtRef_, jmethodID mid_)
Definition: DBTManager.cxx:51
_removeAdapterCBMethodArgs
static const std::string _removeAdapterCBMethodArgs("(II)V")
_addMgmtCBOnce
static void _addMgmtCBOnce(JNIEnv *env, BTManager &mgmt, JNIGlobalRef jmgmtRef, MgmtEvent::Opcode opc, const std::string &jmethodName, const std::string &jmethodArgs)
Definition: DBTManager.cxx:69
BooleanMgmtCBContext
Definition: DBTManager.cxx:46
BooleanMgmtCBContext::opc
MgmtEvent::Opcode opc
Definition: DBTManager.cxx:47
BooleanMgmtCBContext::operator!=
bool operator!=(const BooleanMgmtCBContext &rhs) const
Definition: DBTManager.cxx:63
direct_bt::BTManager::addMgmtEventCallback
bool addMgmtEventCallback(const int dev_id, const MgmtEvent::Opcode opc, const MgmtEventCallback &cb) noexcept
MgmtEventCallback handling
Definition: BTManager.cpp:1117
direct_bt::AdapterSetting::POWERED
@ POWERED
direct_bt::isAdapterSettingBitSet
constexpr bool isAdapterSettingBitSet(const AdapterSetting mask, const AdapterSetting bit) noexcept
Definition: BTTypes1.hpp:177
BTDevice.hpp
direct_bt::BTManager::getAdapter
std::shared_ptr< BTAdapter > getAdapter(const uint16_t dev_id) const noexcept
Returns the DBTAdapter with the given dev_id, or nullptr if not found.
Definition: BTManager.cpp:624
direct_bt::BTAdapter::getName
std::string getName() const noexcept
Returns the system name.
Definition: BTAdapter.hpp:515
direct_bt::BTMode
BTMode
Bluetooth adapter operating mode.
Definition: BTTypes0.hpp:56
direct_bt::MgmtEvent::Opcode::NEW_SETTINGS
@ NEW_SETTINGS
Java_jau_direct_1bt_DBTManager_getAdapterImpl
jobject Java_jau_direct_1bt_DBTManager_getAdapterImpl(JNIEnv *env, jobject obj, jint dev_id)
Definition: DBTManager.cxx:183
DBG_PRINT
#define DBG_PRINT(...)
Use for environment-variable environment::DEBUG conditional debug messages, prefix '[elapsed_time] De...
Definition: debug.hpp:78
Java_jau_direct_1bt_DBTManager_initImpl
void Java_jau_direct_1bt_DBTManager_initImpl(JNIEnv *env, jobject obj, jboolean unifyUUID128Bit, jint jbtMode)
Definition: DBTManager.cxx:112