Qt
Internal/Contributor docs for the Qt SDK. Note: These are NOT official API docs; those are found at https://doc.qt.io/
Loading...
Searching...
No Matches
lowenergynotificationhub.cpp
Go to the documentation of this file.
1// Copyright (C) 2016 The Qt Company Ltd.
2// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR LGPL-3.0-only OR GPL-2.0-only OR GPL-3.0-only
3
5#include "android/jni_android_p.h"
6
7#include <QCoreApplication>
8#include <QtCore/QHash>
9#include <QtCore/QLoggingCategory>
10#include <QtCore/QRandomGenerator>
11#include <QtCore/QJniEnvironment>
12
14
16Q_GLOBAL_STATIC(HubMapType, hubMap)
17
18QReadWriteLock LowEnergyNotificationHub::lock;
19
20Q_DECLARE_LOGGING_CATEGORY(QT_BT_ANDROID)
21
22LowEnergyNotificationHub::LowEnergyNotificationHub(const QBluetoothAddress &remote,
23 bool isPeripheral, QObject *parent)
24 : QObject(parent), javaToCtoken(0)
25{
26 QJniEnvironment env;
27
28 if (isPeripheral) {
29 qCDebug(QT_BT_ANDROID) << "Creating Android Peripheral/Server support for BTLE";
30 jBluetoothLe = QJniObject::construct<QtJniTypes::QtBtLEServer>(
31 QNativeInterface::QAndroidApplication::context());
32 } else {
33 qCDebug(QT_BT_ANDROID) << "Creating Android Central/Client support for BTLE";
34 const QJniObject address =
35 QJniObject::fromString(remote.toString());
36 jBluetoothLe = QJniObject::construct<QtJniTypes::QtBtLECentral>(
37 address.object<jstring>(), QNativeInterface::QAndroidApplication::context());
38 }
39
40 if (!jBluetoothLe.isValid()) return;
41
42 // register C++ class pointer in Java
43 lock.lockForWrite();
44
45 while (true) {
46 javaToCtoken = QRandomGenerator::global()->generate();
47 if (!hubMap()->contains(javaToCtoken))
48 break;
49 }
50
51 hubMap()->insert(javaToCtoken, this);
52 lock.unlock();
53
54 jBluetoothLe.setField<jlong>("qtObject", javaToCtoken);
55}
56
58{
59 lock.lockForWrite();
60 hubMap()->remove(javaToCtoken);
61 lock.unlock();
62}
63
64// runs in Java thread
65void LowEnergyNotificationHub::lowEnergy_connectionChange(JNIEnv *, jobject, jlong qtObject, jint errorCode, jint newState)
66{
67 lock.lockForRead();
68 LowEnergyNotificationHub *hub = hubMap()->value(qtObject);
69 lock.unlock();
70 if (!hub)
71 return;
72
73 QMetaObject::invokeMethod(hub, "connectionUpdated", Qt::QueuedConnection,
74 Q_ARG(QLowEnergyController::ControllerState,
75 (QLowEnergyController::ControllerState)newState),
76 Q_ARG(QLowEnergyController::Error,
77 (QLowEnergyController::Error)errorCode));
78}
79
80void LowEnergyNotificationHub::lowEnergy_mtuChanged(
81 JNIEnv *, jobject, jlong qtObject, jint mtu)
82{
83 lock.lockForRead();
84 LowEnergyNotificationHub *hub = hubMap()->value(qtObject);
85 lock.unlock();
86 if (!hub)
87 return;
88
89 QMetaObject::invokeMethod(hub, "mtuChanged", Qt::QueuedConnection, Q_ARG(int, mtu));
90}
91
92void LowEnergyNotificationHub::lowEnergy_remoteRssiRead(JNIEnv *, jobject, jlong qtObject,
93 int rssi, bool success)
94{
95 lock.lockForRead();
96 LowEnergyNotificationHub *hub = hubMap()->value(qtObject);
97 lock.unlock();
98 if (!hub)
99 return;
100
101 QMetaObject::invokeMethod(hub, "remoteRssiRead", Qt::QueuedConnection,
102 Q_ARG(int, rssi), Q_ARG(bool, success));
103}
104
105
106void LowEnergyNotificationHub::lowEnergy_servicesDiscovered(
107 JNIEnv *, jobject, jlong qtObject, jint errorCode, jstring uuidList)
108{
109 lock.lockForRead();
110 LowEnergyNotificationHub *hub = hubMap()->value(qtObject);
111 lock.unlock();
112 if (!hub)
113 return;
114
115 const QString uuids = QJniObject(uuidList).toString();
116 QMetaObject::invokeMethod(hub, "servicesDiscovered", Qt::QueuedConnection,
117 Q_ARG(QLowEnergyController::Error,
118 (QLowEnergyController::Error)errorCode),
119 Q_ARG(QString, uuids));
120}
121
122void LowEnergyNotificationHub::lowEnergy_serviceDetailsDiscovered(
123 JNIEnv *, jobject, jlong qtObject, jstring uuid, jint startHandle,
124 jint endHandle)
125{
126 lock.lockForRead();
127 LowEnergyNotificationHub *hub = hubMap()->value(qtObject);
128 lock.unlock();
129 if (!hub)
130 return;
131
132 const QString serviceUuid = QJniObject(uuid).toString();
133 QMetaObject::invokeMethod(hub, "serviceDetailsDiscoveryFinished",
134 Qt::QueuedConnection,
135 Q_ARG(QString, serviceUuid),
136 Q_ARG(int, startHandle),
137 Q_ARG(int, endHandle));
138}
139
140void LowEnergyNotificationHub::lowEnergy_characteristicRead(
141 JNIEnv *env, jobject, jlong qtObject, jstring sUuid, jint handle,
142 jstring cUuid, jint properties, jbyteArray data)
143{
144 lock.lockForRead();
145 LowEnergyNotificationHub *hub = hubMap()->value(qtObject);
146 lock.unlock();
147 if (!hub)
148 return;
149
150 const QBluetoothUuid serviceUuid(QJniObject(sUuid).toString());
151 if (serviceUuid.isNull())
152 return;
153
154 const QBluetoothUuid charUuid(QJniObject(cUuid).toString());
155 if (charUuid.isNull())
156 return;
157
158 QByteArray payload;
159 if (data) { //empty Java byte array is 0x0
160 jsize length = env->GetArrayLength(data);
161 payload.resize(length);
162 env->GetByteArrayRegion(data, 0, length,
163 reinterpret_cast<signed char*>(payload.data()));
164 }
165
166 QMetaObject::invokeMethod(hub, "characteristicRead", Qt::QueuedConnection,
167 Q_ARG(QBluetoothUuid, serviceUuid),
168 Q_ARG(int, handle),
169 Q_ARG(QBluetoothUuid, charUuid),
170 Q_ARG(int, properties),
171 Q_ARG(QByteArray, payload));
172
173}
174
175void LowEnergyNotificationHub::lowEnergy_descriptorRead(
176 JNIEnv *env, jobject, jlong qtObject, jstring sUuid, jstring cUuid,
177 jint handle, jstring dUuid, jbyteArray data)
178{
179 lock.lockForRead();
180 LowEnergyNotificationHub *hub = hubMap()->value(qtObject);
181 lock.unlock();
182 if (!hub)
183 return;
184
185 const QBluetoothUuid serviceUuid(QJniObject(sUuid).toString());
186 if (serviceUuid.isNull())
187 return;
188
189 const QBluetoothUuid charUuid(QJniObject(cUuid).toString());
190 const QBluetoothUuid descUuid(QJniObject(dUuid).toString());
191 if (charUuid.isNull() || descUuid.isNull())
192 return;
193
194 QByteArray payload;
195 if (data) { //empty Java byte array is 0x0
196 jsize length = env->GetArrayLength(data);
197 payload.resize(length);
198 env->GetByteArrayRegion(data, 0, length,
199 reinterpret_cast<signed char*>(payload.data()));
200 }
201
202 QMetaObject::invokeMethod(hub, "descriptorRead", Qt::QueuedConnection,
203 Q_ARG(QBluetoothUuid, serviceUuid),
204 Q_ARG(QBluetoothUuid, charUuid),
205 Q_ARG(int, handle),
206 Q_ARG(QBluetoothUuid, descUuid),
207 Q_ARG(QByteArray, payload));
208}
209
210void LowEnergyNotificationHub::lowEnergy_characteristicWritten(
211 JNIEnv *env, jobject, jlong qtObject, jint charHandle,
212 jbyteArray data, jint errorCode)
213{
214 lock.lockForRead();
215 LowEnergyNotificationHub *hub = hubMap()->value(qtObject);
216 lock.unlock();
217 if (!hub)
218 return;
219
220 QByteArray payload;
221 if (data) { //empty Java byte array is 0x0
222 jsize length = env->GetArrayLength(data);
223 payload.resize(length);
224 env->GetByteArrayRegion(data, 0, length,
225 reinterpret_cast<signed char*>(payload.data()));
226 }
227
228 QMetaObject::invokeMethod(hub, "characteristicWritten", Qt::QueuedConnection,
229 Q_ARG(int, charHandle),
230 Q_ARG(QByteArray, payload),
231 Q_ARG(QLowEnergyService::ServiceError,
232 (QLowEnergyService::ServiceError)errorCode));
233}
234
235void LowEnergyNotificationHub::lowEnergy_descriptorWritten(
236 JNIEnv *env, jobject, jlong qtObject, jint descHandle,
237 jbyteArray data, jint errorCode)
238{
239 lock.lockForRead();
240 LowEnergyNotificationHub *hub = hubMap()->value(qtObject);
241 lock.unlock();
242 if (!hub)
243 return;
244
245 QByteArray payload;
246 if (data) { //empty Java byte array is 0x0
247 jsize length = env->GetArrayLength(data);
248 payload.resize(length);
249 env->GetByteArrayRegion(data, 0, length,
250 reinterpret_cast<signed char*>(payload.data()));
251 }
252
253 QMetaObject::invokeMethod(hub, "descriptorWritten", Qt::QueuedConnection,
254 Q_ARG(int, descHandle),
255 Q_ARG(QByteArray, payload),
256 Q_ARG(QLowEnergyService::ServiceError,
257 (QLowEnergyService::ServiceError)errorCode));
258}
259
260void LowEnergyNotificationHub::lowEnergy_serverDescriptorWritten(
261 JNIEnv *env, jobject, jlong qtObject, QtJniTypes::BluetoothGattDescriptor descriptor,
262 jbyteArray newValue)
263{
264 lock.lockForRead();
265 LowEnergyNotificationHub *hub = hubMap()->value(qtObject);
266 lock.unlock();
267 if (!hub)
268 return;
269
270 QByteArray payload;
271 if (newValue) { //empty Java byte array is 0x0
272 jsize length = env->GetArrayLength(newValue);
273 payload.resize(length);
274 env->GetByteArrayRegion(newValue, 0, length,
275 reinterpret_cast<signed char*>(payload.data()));
276 }
277
278 QMetaObject::invokeMethod(hub, "serverDescriptorWritten", Qt::QueuedConnection,
279 Q_ARG(QJniObject, descriptor),
280 Q_ARG(QByteArray, payload));
281}
282
283void LowEnergyNotificationHub::lowEnergy_characteristicChanged(
284 JNIEnv *env, jobject, jlong qtObject, jint charHandle, jbyteArray data)
285{
286 lock.lockForRead();
287 LowEnergyNotificationHub *hub = hubMap()->value(qtObject);
288 lock.unlock();
289 if (!hub)
290 return;
291
292 QByteArray payload;
293 if (data) { //empty Java byte array is 0x0
294 jsize length = env->GetArrayLength(data);
295 payload.resize(length);
296 env->GetByteArrayRegion(data, 0, length,
297 reinterpret_cast<signed char*>(payload.data()));
298 }
299
300 QMetaObject::invokeMethod(hub, "characteristicChanged", Qt::QueuedConnection,
301 Q_ARG(int, charHandle), Q_ARG(QByteArray, payload));
302}
303
304void LowEnergyNotificationHub::lowEnergy_serverCharacteristicChanged(
305 JNIEnv *env, jobject, jlong qtObject,
306 QtJniTypes::BluetoothGattCharacteristic characteristic, jbyteArray newValue)
307{
308 lock.lockForRead();
309 LowEnergyNotificationHub *hub = hubMap()->value(qtObject);
310 lock.unlock();
311 if (!hub)
312 return;
313
314 QByteArray payload;
315 if (newValue) { //empty Java byte array is 0x0
316 jsize length = env->GetArrayLength(newValue);
317 payload.resize(length);
318 env->GetByteArrayRegion(newValue, 0, length,
319 reinterpret_cast<signed char*>(payload.data()));
320 }
321
322 QMetaObject::invokeMethod(hub, "serverCharacteristicChanged", Qt::QueuedConnection,
323 Q_ARG(QJniObject, characteristic),
324 Q_ARG(QByteArray, payload));
325}
326
327void LowEnergyNotificationHub::lowEnergy_serviceError(
328 JNIEnv *, jobject, jlong qtObject, jint attributeHandle, int errorCode)
329{
330 lock.lockForRead();
331 LowEnergyNotificationHub *hub = hubMap()->value(qtObject);
332 lock.unlock();
333 if (!hub)
334 return;
335
336 QMetaObject::invokeMethod(hub, "serviceError", Qt::QueuedConnection,
337 Q_ARG(int, attributeHandle),
338 Q_ARG(QLowEnergyService::ServiceError,
339 (QLowEnergyService::ServiceError)errorCode));
340}
341
342void LowEnergyNotificationHub::lowEnergy_advertisementError(
343 JNIEnv *, jobject, jlong qtObject, jint status)
344{
345 lock.lockForRead();
346 LowEnergyNotificationHub *hub = hubMap()->value(qtObject);
347 lock.unlock();
348 if (!hub)
349 return;
350
351 QMetaObject::invokeMethod(hub, "advertisementError", Qt::QueuedConnection,
352 Q_ARG(int, status));
353}
354
355QT_END_NAMESPACE
QT_BEGIN_NAMESPACE typedef QHash< long, LowEnergyNotificationHub * > HubMapType