Direct-BT v3.3.0-1-gc2d430c
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
37
38using namespace direct_bt;
39using namespace jau::jni;
40
41static const std::string _removeAdapterCBMethodName("removeAdapterCB");
42static const std::string _removeAdapterCBMethodArgs("(II)V");
43static const std::string _updatedAdapterCBMethodName("updatedAdapterCB");
44static const std::string _updatedAdapterCBMethodArgs("(II)V");
45
49 jmethodID mid;
50
51 BooleanMgmtCBContext(MgmtEvent::Opcode opc_, JNIGlobalRef jmgmtRef_, jmethodID mid_)
52 : opc(opc_), jmgmtRef(std::move(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};
67typedef std::shared_ptr<BooleanMgmtCBContext> BooleanMgmtCBContextRef;
68
69static void _addMgmtCBOnce(JNIEnv *env, BTManager & mgmt, const JNIGlobalRef& jmgmtRef, MgmtEvent::Opcode opc,
70 const std::string &jmethodName, const std::string &jmethodArgs)
71{
72 try {
73 void(*nativeCallback)(BooleanMgmtCBContextRef&, const MgmtEvent&) =
74 [](BooleanMgmtCBContextRef& ctx_ref, const MgmtEvent& e)->void {
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 };
90
91
92 jclass mgmtClazz = search_class(env, jmgmtRef.getObject());
94 if( nullptr == mgmtClazz ) {
95 throw jau::InternalError("BTManager not found", E_FILE_LINE);
96 }
97 jmethodID mid = search_method(env, mgmtClazz, jmethodName.c_str(), jmethodArgs.c_str(), false);
99 if( nullptr == mid ) {
100 throw jau::InternalError("BTManager has no "+jmethodName+"."+jmethodArgs+" method, for "+mgmt.toString(), E_FILE_LINE);
101 }
102
103 // move BooleanDeviceCBContextRef into jau::func::capval_target_t and operator== includes javaCallback comparison
104 jau::function<void(const MgmtEvent&)> funcDef = jau::bind_capval(std::make_shared<BooleanMgmtCBContext>(opc, jmgmtRef, mid), nativeCallback);
105 mgmt.addMgmtEventCallback(-1, opc, funcDef);
106 } catch(...) {
108 }
109}
110
111jlong Java_jau_direct_1bt_DBTManager_ctorImpl(JNIEnv *env, jobject obj)
112{
113 try {
115 JNIGlobalRef global_obj(obj); // lock instance first (global reference), inserted below
117 ref->setJavaObject( std::make_shared<JavaGlobalObj>( std::move(global_obj), nullptr ) );
118 JavaGlobalObj::check(ref->getJavaObject(), E_FILE_LINE);
119
120 JNIGlobalRef jmgmtRef = JavaGlobalObj::GetJavaObject(ref->getJavaObject());
121 _addMgmtCBOnce(env, *ref, jmgmtRef, MgmtEvent::Opcode::INDEX_REMOVED, _removeAdapterCBMethodName, _removeAdapterCBMethodArgs);
122 _addMgmtCBOnce(env, *ref, jmgmtRef, MgmtEvent::Opcode::INDEX_ADDED, _updatedAdapterCBMethodName, _updatedAdapterCBMethodArgs);
123 _addMgmtCBOnce(env, *ref, jmgmtRef, MgmtEvent::Opcode::NEW_SETTINGS, _updatedAdapterCBMethodName, _updatedAdapterCBMethodArgs);
124 DBG_PRINT("Java_jau_direct_1bt_DBTManager_init: Manager %s", ref->toString().c_str());
125 return ref.release_to_jlong();
126 } catch(...) {
128 }
129 return (jlong) (intptr_t)nullptr;
130}
131
132void Java_jau_direct_1bt_DBTManager_dtorImpl(JNIEnv *env, jobject obj, jlong nativeInstance)
133{
134 (void)obj;
135 try {
136 shared_ptr_ref<BTManager> manager(nativeInstance, false /* throw_on_nullptr */); // hold copy until done
137 if( nullptr != manager.pointer() ) {
138 if( !manager.is_null() ) {
139 JavaAnonRef manager_java = manager->getJavaObject(); // hold until done!
140 JavaGlobalObj::check(manager_java, E_FILE_LINE);
141 manager->setJavaObject();
142 manager->close();
143 }
144 std::shared_ptr<BTManager>* ref_ptr = castInstance<BTManager>(nativeInstance);
145 delete ref_ptr;
146 }
147 } catch(...) {
149 }
150}
151
152static const std::string _adapterClazzCtorArgs("(J[BBLjava/lang/String;I)V");
153static jobject _createJavaAdapter(JNIEnv *env_, jclass clazz, jmethodID clazz_ctor, const std::shared_ptr<BTAdapter>& adapter) {
154 // prepare adapter ctor
155 const EUI48 addr = adapter->getAddressAndType().address;
156 jbyteArray jaddr = env_->NewByteArray(sizeof(addr));
157 env_->SetByteArrayRegion(jaddr, 0, sizeof(addr), (const jbyte*)(addr.b));
159 const jstring name = from_string_to_jstring(env_, adapter->getName());
161 shared_ptr_ref<BTAdapter> adapter_ref( adapter );
162 jobject jAdapter = env_->NewObject(clazz, clazz_ctor, adapter_ref.release_to_jlong(), jaddr, adapter->getAddressAndType().type, name, adapter->dev_id);
164 JNIGlobalRef::check(jAdapter, E_FILE_LINE);
165 JavaAnonRef jAdapterRef = adapter->getJavaObject(); // GlobalRef
166 JavaGlobalObj::check(jAdapterRef, E_FILE_LINE);
167 env_->DeleteLocalRef(jaddr);
168 env_->DeleteLocalRef(name);
169 env_->DeleteLocalRef(jAdapter);
170
171 DBG_PRINT("Java_jau_direct_1bt_DBTManager_createJavaAdapter: New Adapter %p %s", adapter.get(), adapter->toString().c_str());
172 return JavaGlobalObj::GetObject(jAdapterRef);
173};
174
176{
177 try {
178 shared_ptr_ref<BTManager> ref(env, obj); // hold until done
179 DBG_PRINT("Java_jau_direct_1bt_DBTManager_getAdapterListImpl: Manager %s", ref->toString().c_str());
180
181 jau::darray<std::shared_ptr<BTAdapter>> adapters = ref->getAdapters();
182 return convert_vector_sharedptr_to_jarraylist<jau::darray<std::shared_ptr<BTAdapter>>, BTAdapter>(
183 env, adapters, _adapterClazzCtorArgs.c_str(), _createJavaAdapter);
184 } catch(...) {
186 }
187 return nullptr;
188}
189
190jobject Java_jau_direct_1bt_DBTManager_getAdapterImpl(JNIEnv *env, jobject obj, jint dev_id)
191{
192 try {
193 shared_ptr_ref<BTManager> ref(env, obj); // hold until done
194
195 std::shared_ptr<BTAdapter> adapter = ref->getAdapter(dev_id);
196 if( nullptr == adapter ) {
197 ERR_PRINT("BTManager::getAdapterImpl: Adapter dev_id %d: Not found", dev_id);
198 return nullptr;
199 }
200 DBG_PRINT("BTManager::getAdapterImpl: Adapter dev_id %d: %s", dev_id, adapter->toString().c_str());
201
202 return convert_instance_to_jobject<BTAdapter>(env, adapter, _adapterClazzCtorArgs.c_str(), _createJavaAdapter);
203 } catch(...) {
205 }
206 return nullptr;
207}
static void _addMgmtCBOnce(JNIEnv *env, BTManager &mgmt, const JNIGlobalRef &jmgmtRef, MgmtEvent::Opcode opc, const std::string &jmethodName, const std::string &jmethodArgs)
Definition: DBTManager.cxx:69
static const std::string _removeAdapterCBMethodArgs("(II)V")
jobject Java_jau_direct_1bt_DBTManager_getAdapterListImpl(JNIEnv *env, jobject obj)
Definition: DBTManager.cxx:175
jlong Java_jau_direct_1bt_DBTManager_ctorImpl(JNIEnv *env, jobject obj)
Definition: DBTManager.cxx:111
static const std::string _adapterClazzCtorArgs("(J[BBLjava/lang/String;I)V")
jobject Java_jau_direct_1bt_DBTManager_getAdapterImpl(JNIEnv *env, jobject obj, jint dev_id)
Definition: DBTManager.cxx:190
static const std::string _updatedAdapterCBMethodArgs("(II)V")
void Java_jau_direct_1bt_DBTManager_dtorImpl(JNIEnv *env, jobject obj, jlong nativeInstance)
Definition: DBTManager.cxx:132
std::shared_ptr< BooleanMgmtCBContext > BooleanMgmtCBContextRef
Definition: DBTManager.cxx:67
static jobject _createJavaAdapter(JNIEnv *env_, jclass clazz, jmethodID clazz_ctor, const std::shared_ptr< BTAdapter > &adapter)
Definition: DBTManager.cxx:153
static const std::string _updatedAdapterCBMethodName("updatedAdapterCB")
static const std::string _removeAdapterCBMethodName("removeAdapterCB")
#define E_FILE_LINE
BTAdapter represents one local Bluetooth Controller.
Definition: BTAdapter.hpp:324
A thread safe singleton handler of the BTAdapter manager, e.g.
Definition: BTManager.hpp:204
std::string toString() const noexcept override
Definition: BTManager.hpp:370
bool addMgmtEventCallback(const int dev_id, const MgmtEvent::Opcode opc, const MgmtEventCallback &cb) noexcept
MgmtEventCallback handling
Definition: BTManager.cpp:1163
uint16_t opcode, uint16_t dev-id, uint16_t param_size
Definition: MgmtTypes.hpp:1402
static uint16_t getDevID(const uint8_t *data)
Definition: MgmtTypes.hpp:363
Implementation of a dynamic linear array storage, aka vector.
Definition: darray.hpp:148
Class template jau::function is a general-purpose static-polymorphic function wrapper.
jobject getObject() const noexcept
A std::shared_ptr<T> storage instance to be copied from and released into a java object's long native...
Definition: helper_jni.hpp:393
bool is_null() const noexcept
Returns true if either this instances shared_ptr<T> storage or the managed object reference is nullpt...
Definition: helper_jni.hpp:614
std::shared_ptr< T > * pointer() noexcept
Provides access to the shared_ptr<T> pointer, l-value of storage.
Definition: helper_jni.hpp:621
std::string toString() const noexcept
Definition: helper_jni.hpp:657
jlong release_to_jlong() noexcept
Release ownership and return the jlong representation of the shared_ptr<T> storage.
Definition: helper_jni.hpp:574
#define ERR_PRINT(...)
Use for unconditional error messages, prefix '[elapsed_time] Error @ FILE:LINE FUNC: '.
Definition: debug.hpp:109
#define DBG_PRINT(...)
Use for environment-variable environment::DEBUG conditional debug messages, prefix '[elapsed_time] De...
Definition: debug.hpp:52
Entry * get(const EUI48 &addr, const std::string &name, AddressNameEntryMatchFunc m) noexcept
Returns a matching BTSecurityRegistry::Entry with the given addr and/or name.
constexpr bool isAdapterSettingBitSet(const AdapterSetting mask, const AdapterSetting bit) noexcept
Definition: BTTypes1.hpp:185
jau::function< R(A...)> bind_capval(const I &data, R(*func)(I &, A...)) noexcept
Bind given data by copying the captured value and the given non-void function to an anonymous functio...
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.
thread_local JNIEnvContainer jni_env
jstring from_string_to_jstring(JNIEnv *env, const std::string &str)
jmethodID search_method(JNIEnv *env, jclass clazz, const char *method_name, const char *prototype, bool is_static)
std::shared_ptr< JavaAnon > JavaAnonRef
Definition: java_uplink.hpp:55
jclass search_class(JNIEnv *env, const char *clazz_name)
#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:52
STL namespace.
bool operator!=(const BooleanMgmtCBContext &rhs) const
Definition: DBTManager.cxx:63
JNIGlobalRef jmgmtRef
Definition: DBTManager.cxx:48
BooleanMgmtCBContext(MgmtEvent::Opcode opc_, JNIGlobalRef jmgmtRef_, jmethodID mid_)
Definition: DBTManager.cxx:51
bool operator==(const BooleanMgmtCBContext &rhs) const
Definition: DBTManager.cxx:54
MgmtEvent::Opcode opc
Definition: DBTManager.cxx:47
A packed 48 bit EUI-48 identifier, formerly known as MAC-48 or simply network device MAC address (Med...
Definition: eui48.hpp:324
uint8_t b[6]
Definition: eui48.hpp:324