Qt
Internal/Contributor docs for the Qt SDK. <b>Note:</b> These are NOT official API docs; those are found <a href='https://doc.qt.io/'>here</a>.
Loading...
Searching...
No Matches
devicediscoverybroadcastreceiver.cpp
Go to the documentation of this file.
1// Copyright (C) 2016 Lauri Laanmets (Proekspert AS) <lauri.laanmets@eesti.ee>
2// Copyright (C) 2016 The Qt Company Ltd.
3// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR LGPL-3.0-only OR GPL-2.0-only OR GPL-3.0-only
4
6#include <QCoreApplication>
7#include <QtCore/QtEndian>
8#include <QtCore/QLoggingCategory>
9#include <QtBluetooth/QBluetoothAddress>
10#include <QtBluetooth/QBluetoothDeviceInfo>
11#include <QtBluetooth/QBluetoothUuid>
13#include <QtCore/QHash>
14#include <QtCore/qbitarray.h>
15#include <algorithm>
16
18
19Q_DECLARE_LOGGING_CATEGORY(QT_BT_ANDROID)
20
21typedef QHash<jint, QBluetoothDeviceInfo::CoreConfigurations> JCachedBtTypes;
22Q_GLOBAL_STATIC(JCachedBtTypes, cachedBtTypes)
23typedef QHash<jint, QBluetoothDeviceInfo::MajorDeviceClass> JCachedMajorTypes;
24Q_GLOBAL_STATIC(JCachedMajorTypes, cachedMajorTypes)
25
27Q_GLOBAL_STATIC(JCachedMinorTypes, cachedMinorTypes)
28
30{
31 const qsizetype numberOfMajorDeviceClasses = 11; // count QBluetoothDeviceInfo::MajorDeviceClass values
32
33 // switch below used to ensure that we notice additions to MajorDeviceClass enum
35 switch (classes) {
47 break;
48 default:
49 qCWarning(QT_BT_ANDROID) << "Unknown category of major device class:" << classes;
50 }
51
52 return QBitArray(numberOfMajorDeviceClasses, false);
53}
54
56
57
58// class names
59static const char javaBluetoothDeviceClassName[] = "android/bluetooth/BluetoothDevice";
60static const char javaBluetoothClassDeviceMajorClassName[] = "android/bluetooth/BluetoothClass$Device$Major";
61static const char javaBluetoothClassDeviceClassName[] = "android/bluetooth/BluetoothClass$Device";
62
63// field names device type (LE vs classic)
64static const char javaDeviceTypeClassic[] = "DEVICE_TYPE_CLASSIC";
65static const char javaDeviceTypeDual[] = "DEVICE_TYPE_DUAL";
66static const char javaDeviceTypeLE[] = "DEVICE_TYPE_LE";
67static const char javaDeviceTypeUnknown[] = "DEVICE_TYPE_UNKNOWN";
68
70{
71 const char javaFieldName[14];
73};
74static_assert(sizeof(MajorClassJavaToQtMapping) == 16);
75
89
90// QBluetoothDeviceInfo::MajorDeviceClass value plus 1 matches index
91// UncategorizedDevice shifts to index 0
92static constexpr quint8 minorIndexSizes[] = {
93 64, // QBluetoothDevice::UncategorizedDevice
94 61, // QBluetoothDevice::MiscellaneousDevice
95 18, // QBluetoothDevice::ComputerDevice
96 35, // QBluetoothDevice::PhoneDevice
97 62, // QBluetoothDevice::NetworkDevice
98 0, // QBluetoothDevice::AudioVideoDevice
99 56, // QBluetoothDevice::PeripheralDevice
100 63, // QBluetoothDevice::ImagingDEvice
101 49, // QBluetoothDevice::WearableDevice
102 42, // QBluetoothDevice::ToyDevice
103 26, // QBluetoothDevice::HealthDevice
104};
105
111
113 // QBluetoothDevice::AudioVideoDevice -> 17 entries
114 { "AUDIO_VIDEO_CAMCORDER", QBluetoothDeviceInfo::Camcorder }, //index 0
115 { "AUDIO_VIDEO_CAR_AUDIO", QBluetoothDeviceInfo::CarAudio },
116 { "AUDIO_VIDEO_HANDSFREE", QBluetoothDeviceInfo::HandsFreeDevice },
117 { "AUDIO_VIDEO_HEADPHONES", QBluetoothDeviceInfo::Headphones },
118 { "AUDIO_VIDEO_HIFI_AUDIO", QBluetoothDeviceInfo::HiFiAudioDevice },
119 { "AUDIO_VIDEO_LOUDSPEAKER", QBluetoothDeviceInfo::Loudspeaker },
120 { "AUDIO_VIDEO_MICROPHONE", QBluetoothDeviceInfo::Microphone },
121 { "AUDIO_VIDEO_PORTABLE_AUDIO", QBluetoothDeviceInfo::PortableAudioDevice },
122 { "AUDIO_VIDEO_SET_TOP_BOX", QBluetoothDeviceInfo::SetTopBox },
123 { "AUDIO_VIDEO_UNCATEGORIZED", QBluetoothDeviceInfo::UncategorizedAudioVideoDevice },
124 { "AUDIO_VIDEO_VCR", QBluetoothDeviceInfo::Vcr },
125 { "AUDIO_VIDEO_VIDEO_CAMERA", QBluetoothDeviceInfo::VideoCamera },
126 { "AUDIO_VIDEO_VIDEO_CONFERENCING", QBluetoothDeviceInfo::VideoConferencing },
127 { "AUDIO_VIDEO_VIDEO_DISPLAY_AND_LOUDSPEAKER", QBluetoothDeviceInfo::VideoDisplayAndLoudspeaker },
128 { "AUDIO_VIDEO_VIDEO_GAMING_TOY", QBluetoothDeviceInfo::GamingDevice },
129 { "AUDIO_VIDEO_VIDEO_MONITOR", QBluetoothDeviceInfo::VideoMonitor },
130 { "AUDIO_VIDEO_WEARABLE_HEADSET", QBluetoothDeviceInfo::WearableHeadsetDevice },
131 { nullptr, 0 }, // separator
132
133 // QBluetoothDevice::ComputerDevice -> 7 entries
134 { "COMPUTER_UNCATEGORIZED", QBluetoothDeviceInfo::UncategorizedComputer }, // index 18
135 { "COMPUTER_DESKTOP", QBluetoothDeviceInfo::DesktopComputer },
136 { "COMPUTER_HANDHELD_PC_PDA", QBluetoothDeviceInfo::HandheldComputer },
137 { "COMPUTER_LAPTOP", QBluetoothDeviceInfo::LaptopComputer },
138 { "COMPUTER_PALM_SIZE_PC_PDA", QBluetoothDeviceInfo::HandheldClamShellComputer },
139 { "COMPUTER_SERVER", QBluetoothDeviceInfo::ServerComputer },
140 { "COMPUTER_WEARABLE", QBluetoothDeviceInfo::WearableComputer },
141 { nullptr, 0 }, // separator
142
143 // QBluetoothDevice::HealthDevice -> 8 entries
144 { "HEALTH_BLOOD_PRESSURE", QBluetoothDeviceInfo::HealthBloodPressureMonitor }, // index 26
145 { "HEALTH_DATA_DISPLAY", QBluetoothDeviceInfo::HealthDataDisplay },
146 { "HEALTH_GLUCOSE", QBluetoothDeviceInfo::HealthGlucoseMeter },
147 { "HEALTH_PULSE_OXIMETER", QBluetoothDeviceInfo::HealthPulseOximeter },
148 { "HEALTH_PULSE_RATE", QBluetoothDeviceInfo::HealthStepCounter },
149 { "HEALTH_THERMOMETER", QBluetoothDeviceInfo::HealthThermometer },
150 { "HEALTH_UNCATEGORIZED", QBluetoothDeviceInfo::UncategorizedHealthDevice },
151 { "HEALTH_WEIGHING", QBluetoothDeviceInfo::HealthWeightScale },
152 { nullptr, 0 }, // separator
153
154 // QBluetoothDevice::PhoneDevice -> 6 entries
155 { "PHONE_CELLULAR", QBluetoothDeviceInfo::CellularPhone }, // index 35
156 { "PHONE_CORDLESS", QBluetoothDeviceInfo::CordlessPhone },
158 { "PHONE_MODEM_OR_GATEWAY", QBluetoothDeviceInfo::WiredModemOrVoiceGatewayPhone },
159 { "PHONE_SMART", QBluetoothDeviceInfo::SmartPhone },
160 { "PHONE_UNCATEGORIZED", QBluetoothDeviceInfo::UncategorizedPhone },
161 { nullptr, 0 }, // separator
162
163 // QBluetoothDevice::ToyDevice -> 6 entries
164 { "TOY_CONTROLLER", QBluetoothDeviceInfo::ToyController }, // index 42
165 { "TOY_DOLL_ACTION_FIGURE", QBluetoothDeviceInfo::ToyDoll },
166 { "TOY_GAME", QBluetoothDeviceInfo::ToyGame },
167 { "TOY_ROBOT", QBluetoothDeviceInfo::ToyRobot },
168 { "TOY_UNCATEGORIZED", QBluetoothDeviceInfo::UncategorizedToy },
169 { "TOY_VEHICLE", QBluetoothDeviceInfo::ToyVehicle },
170 { nullptr, 0 }, // separator
171
172 // QBluetoothDevice::WearableDevice -> 6 entries
173 { "WEARABLE_GLASSES", QBluetoothDeviceInfo::WearableGlasses }, // index 49
174 { "WEARABLE_HELMET", QBluetoothDeviceInfo::WearableHelmet },
175 { "WEARABLE_JACKET", QBluetoothDeviceInfo::WearableJacket },
176 { "WEARABLE_PAGER", QBluetoothDeviceInfo::WearablePager },
177 { "WEARABLE_UNCATEGORIZED", QBluetoothDeviceInfo::UncategorizedWearableDevice },
178 { "WEARABLE_WRIST_WATCH", QBluetoothDeviceInfo::WearableWristWatch },
179 { nullptr, 0 }, // separator
180
181 // QBluetoothDevice::PeripheralDevice -> 3 entries
182 // For some reason these are not mentioned in Android docs but still exist
183 { "PERIPHERAL_NON_KEYBOARD_NON_POINTING", QBluetoothDeviceInfo::UncategorizedPeripheral }, // index 56
184 { "PERIPHERAL_KEYBOARD", QBluetoothDeviceInfo::KeyboardPeripheral },
185 { "PERIPHERAL_POINTING", QBluetoothDeviceInfo::PointingDevicePeripheral },
186 { "PERIPHERAL_KEYBOARD_POINTING", QBluetoothDeviceInfo::KeyboardWithPointingDevicePeripheral },
187 { nullptr, 0 }, // separator
188
189 // the following entries do not exist on Android
190 // we map them to the unknown minor version case
191 // QBluetoothDevice::Miscellaneous
192 { nullptr, 0 }, // index 61 & separator
193
194 // QBluetoothDevice::NetworkDevice
195 { nullptr, 0 }, // index 62 & separator
196
197 // QBluetoothDevice::ImagingDevice
198 { nullptr, 0 }, // index 63 & separator
199
200 // QBluetoothDevice::UncategorizedDevice
201 { nullptr, 0 }, // index 64 & separator
202};
203
204/*
205 Advertising Data Type (AD type) for LE scan records, as defined in
206 https://www.bluetooth.com/specifications/assigned-numbers/generic-access-profile
207*/
223
224QBluetoothDeviceInfo::CoreConfigurations qtBtTypeForJavaBtType(jint javaType)
225{
226 const JCachedBtTypes::iterator it = cachedBtTypes()->find(javaType);
227 if (it == cachedBtTypes()->end()) {
228
229 if (javaType == QJniObject::getStaticField<jint>(
230 javaBluetoothDeviceClassName, javaDeviceTypeClassic)) {
231 cachedBtTypes()->insert(javaType,
234 } else if (javaType == QJniObject::getStaticField<jint>(
235 javaBluetoothDeviceClassName, javaDeviceTypeLE)) {
236 cachedBtTypes()->insert(javaType,
239 } else if (javaType == QJniObject::getStaticField<jint>(
240 javaBluetoothDeviceClassName, javaDeviceTypeDual)) {
241 cachedBtTypes()->insert(javaType,
244 } else if (javaType == QJniObject::getStaticField<jint>(
245 javaBluetoothDeviceClassName, javaDeviceTypeUnknown)) {
246 cachedBtTypes()->insert(javaType,
248 } else {
249 qCWarning(QT_BT_ANDROID) << "Unknown Bluetooth device type value";
250 }
251
253 } else {
254 return it.value();
255 }
256}
257
259{
260 const JCachedMajorTypes::iterator it = cachedMajorTypes()->find(javaType);
261 if (it == cachedMajorTypes()->end()) {
262 QJniEnvironment env;
263 // precache all major device class fields
264 jint fieldValue;
266 auto clazz = env->FindClass(javaBluetoothClassDeviceMajorClassName);
267 for (const auto &majorMapping : majorMappings) {
268 auto fieldId = env->GetStaticFieldID(clazz, majorMapping.javaFieldName, "I");
269 if (!env->ExceptionCheck())
270 fieldValue = env->GetStaticIntField(clazz, fieldId);
271 if (env.checkAndClearExceptions()) {
272 qCWarning(QT_BT_ANDROID) << "Unknown BluetoothClass.Device.Major field" << javaType;
273
274 // add fallback value because field not readable
275 cachedMajorTypes()->insert(javaType, QBluetoothDeviceInfo::UncategorizedDevice);
276 } else {
277 cachedMajorTypes()->insert(fieldValue, majorMapping.qtMajor);
278 }
279
280 if (fieldValue == javaType)
281 result = majorMapping.qtMajor;
282 }
283
284 return result;
285 } else {
286 return it.value();
287 }
288}
289
290/*
291 The index for major into the MinorClassJavaToQtMapping and initializedCacheTracker
292 is major+1 except for UncategorizedDevice which is at index 0.
293*/
295{
296 int mappingIndex = (int) major;
298 mappingIndex = 0;
299 else
300 mappingIndex++;
301
302 Q_ASSERT(mappingIndex >=0
303 && mappingIndex <= (QBluetoothDeviceInfo::HealthDevice + 1));
304
305 return mappingIndex;
306}
307
309{
310 //qCDebug(QT_BT_ANDROID) << "Caching minor values for major" << major;
311 int mappingIndex = mappingIndexForMajor(major);
312 quint8 sizeIndex = minorIndexSizes[mappingIndex];
313
314 while (minorMappings[sizeIndex].javaFieldName != nullptr) {
315 jint fieldValue = QJniObject::getStaticField<jint>(
316 javaBluetoothClassDeviceClassName, minorMappings[sizeIndex].javaFieldName);
317
318 Q_ASSERT(fieldValue >= 0);
319 cachedMinorTypes()->insert(fieldValue, minorMappings[sizeIndex].qtMinor);
320 sizeIndex++;
321 }
322
323 initializedCacheTracker()->setBit(mappingIndex);
324}
325
327{
328 // there are no minor device classes in java with value 0
329 //qCDebug(QT_BT_ANDROID) << "received minor class device:" << javaMinor;
330 if (javaMinor == 0)
331 return 0;
332
333 int mappingIndex = mappingIndexForMajor(major);
334
335 // whenever we encounter a not yet seen major device class
336 // we populate the cache with all its related minor values
337 if (!initializedCacheTracker()->at(mappingIndex))
339
340 const JCachedMinorTypes::iterator it = cachedMinorTypes()->find(javaMinor);
341 if (it == cachedMinorTypes()->end())
342 return 0;
343 else
344 return it.value();
345}
346
347
349{
350 addAction(QJniObject::fromString(
351 valueForStaticField<QtJniTypes::BluetoothDevice, JavaNames::ActionFound>()));
352 addAction(QJniObject::fromString(
353 valueForStaticField<QtJniTypes::BluetoothAdapter, JavaNames::ActionDiscoveryStarted>()));
354 addAction(QJniObject::fromString(
355 valueForStaticField<QtJniTypes::BluetoothAdapter, JavaNames::ActionDiscoveryFinished>()));
356}
357
358// Runs in Java thread
359void DeviceDiscoveryBroadcastReceiver::onReceive(JNIEnv *env, jobject context, jobject intent)
360{
362 Q_UNUSED(env)
363
364 QJniObject intentObject(intent);
365 const QString action = intentObject.callMethod<jstring>("getAction").toString();
366
367 qCDebug(QT_BT_ANDROID) << "DeviceDiscoveryBroadcastReceiver::onReceive() - event:" << action;
368
369 if (action == valueForStaticField<QtJniTypes::BluetoothAdapter,
371 emit finished();
372 } else if (action == valueForStaticField<QtJniTypes::BluetoothAdapter,
375 } else if (action == valueForStaticField<QtJniTypes::BluetoothDevice,
377 //get BluetoothDevice
378 QJniObject keyExtra =
379 QJniObject::fromString(valueForStaticField<QtJniTypes::BluetoothDevice,
381 const QJniObject bluetoothDevice =
382 intentObject.callMethod<QtJniTypes::Parcelable>("getParcelableExtra",
383 keyExtra.object<jstring>());
384
385 if (!bluetoothDevice.isValid())
386 return;
387
388 keyExtra = QJniObject::fromString(valueForStaticField<QtJniTypes::BluetoothDevice,
390 int rssi = intentObject.callMethod<jshort>("getShortExtra",
391 keyExtra.object<jstring>(), jshort(0));
392
393 const QBluetoothDeviceInfo info = retrieveDeviceInfo(bluetoothDevice, rssi);
394 if (info.isValid())
395 emit deviceDiscovered(info, false);
396 }
397}
398
399// Runs in Java thread
401 JNIEnv */*env*/, jobject jBluetoothDevice, jint rssi, jbyteArray scanRecord)
402{
403 const QJniObject bluetoothDevice(jBluetoothDevice);
404 if (!bluetoothDevice.isValid())
405 return;
406
407 const QBluetoothDeviceInfo info = retrieveDeviceInfo(bluetoothDevice, rssi, scanRecord);
408 if (info.isValid())
410}
411
412QBluetoothDeviceInfo DeviceDiscoveryBroadcastReceiver::retrieveDeviceInfo(const QJniObject &bluetoothDevice, int rssi, jbyteArray scanRecord)
413{
414 const QString deviceName = bluetoothDevice.callMethod<jstring>("getName").toString();
415 const QBluetoothAddress deviceAddress(
416 bluetoothDevice.callMethod<jstring>("getAddress").toString());
417 const QJniObject bluetoothClass =
418 bluetoothDevice.callMethod<QtJniTypes::BluetoothClass>("getBluetoothClass");
419
420 if (!bluetoothClass.isValid())
421 return QBluetoothDeviceInfo();
422
424 bluetoothClass.callMethod<jint>("getMajorDeviceClass"));
425 // major device class is 5 bits from index 8 - 12
426 quint32 classType = ((quint32(majorClass) & 0x1f) << 8);
427
428 jint javaMinor = bluetoothClass.callMethod<jint>("getDeviceClass");
429 quint8 minorDeviceType = resolveAndroidMinorClass(majorClass, javaMinor);
430
431 // minor device class is 6 bits from index 2 - 7
432 classType |= ((quint32(minorDeviceType) & 0x3f) << 2);
433
434 static constexpr quint32 services[] = {
443 };
444
445 // Matching BluetoothClass.Service values
446 quint32 serviceResult = 0;
447 for (quint32 current : services) {
448 int androidId = (current << 16); // Android values shift by 2 bytes compared to Qt enums
449 if (bluetoothClass.callMethod<jboolean>("hasService", androidId))
450 serviceResult |= current;
451 }
452
453 // service class info is 11 bits from index 13 - 23
454 classType |= (serviceResult << 13);
455
456 QBluetoothDeviceInfo info(deviceAddress, deviceName, classType);
457 info.setRssi(rssi);
458 QJniEnvironment env;
459 if (scanRecord != nullptr) {
460 // Parse scan record
461 jboolean isCopy;
462 jbyte *elems = env->GetByteArrayElements(scanRecord, &isCopy);
463 const char *scanRecordBuffer = reinterpret_cast<const char *>(elems);
464 const jsize scanRecordLength = env->GetArrayLength(scanRecord);
465
466 QList<QBluetoothUuid> serviceUuids;
467 jsize i = 0;
468
469 // Spec 4.2, Vol 3, Part C, Chapter 11
470 QString localName;
471 while (i < scanRecordLength) {
472 // sizeof(EIR Data) = sizeof(Length) + sizeof(EIR data Type) + sizeof(EIR Data)
473 // Length = sizeof(EIR data Type) + sizeof(EIR Data)
474
475 const int nBytes = scanRecordBuffer[i];
476 if (nBytes == 0)
477 break;
478
479 if (i >= scanRecordLength - nBytes)
480 break;
481
482 const int adType = scanRecordBuffer[i+1];
483 const char *dataPtr = &scanRecordBuffer[i+2];
484 QBluetoothUuid foundService;
485
486 switch (adType) {
489 foundService = QBluetoothUuid(qFromLittleEndian<quint16>(dataPtr));
490 break;
493 foundService = QBluetoothUuid(qFromLittleEndian<quint32>(dataPtr));
494 break;
497 foundService =
498 QBluetoothUuid(qToBigEndian<QUuid::Id128Bytes>(qFromLittleEndian<QUuid::Id128Bytes>(dataPtr)));
499 break;
501 if (nBytes >= 3) {
502 info.setServiceData(QBluetoothUuid(qFromLittleEndian<quint16>(dataPtr)),
503 QByteArray(dataPtr + 2, nBytes - 3));
504 }
505 break;
507 if (nBytes >= 5) {
508 info.setServiceData(QBluetoothUuid(qFromLittleEndian<quint32>(dataPtr)),
509 QByteArray(dataPtr + 4, nBytes - 5));
510 }
511 break;
513 if (nBytes >= 17) {
514 info.setServiceData(QBluetoothUuid(qToBigEndian<QUuid::Id128Bytes>(
515 qFromLittleEndian<QUuid::Id128Bytes>(dataPtr))),
516 QByteArray(dataPtr + 16, nBytes - 17));
517 }
518 break;
520 if (nBytes >= 3) {
521 info.setManufacturerData(qFromLittleEndian<quint16>(dataPtr),
522 QByteArray(dataPtr + 2, nBytes - 3));
523 }
524 break;
525 // According to Spec 5.0, Vol 3, Part C, Chapter 12.1
526 // the device's local name is utf8 encoded
528 if (localName.isEmpty())
529 localName = QString::fromUtf8(dataPtr, nBytes - 1);
530 break;
532 localName = QString::fromUtf8(dataPtr, nBytes - 1);
533 break;
534 default:
535 // qWarning() << "Unhandled AD Type" << Qt::hex << adType;
536 // no other types supported yet and therefore skipped
537 // https://www.bluetooth.com/specifications/assigned-numbers/generic-access-profile
538 break;
539 }
540
541 i += nBytes + 1;
542
543 if (!foundService.isNull() && !serviceUuids.contains(foundService))
544 serviceUuids.append(foundService);
545 }
546
547 if (info.name().isEmpty())
548 info.setName(localName);
549
550 info.setServiceUuids(serviceUuids);
551
552 env->ReleaseByteArrayElements(scanRecord, elems, JNI_ABORT);
553 }
554
555 auto methodId = env.findMethod(bluetoothDevice.objectClass(), "getType", "()I");
556 jint javaBtType = env->CallIntMethod(bluetoothDevice.object(), methodId);
557 if (!env.checkAndClearExceptions()) {
558 info.setCoreConfigurations(qtBtTypeForJavaBtType(javaBtType));
559 }
560
561 return info;
562}
563
quint8 rssi
std::vector< ObjCStrongReference< CBMutableService > > services
void addAction(const QJniObject &filter)
virtual void onReceiveLeScan(JNIEnv *env, jobject jBluetoothDevice, jint rssi, jbyteArray scanRecord)
virtual void onReceive(JNIEnv *env, jobject context, jobject intent)
void deviceDiscovered(const QBluetoothDeviceInfo &info, bool isLeScanResult)
\inmodule QtCore
Definition qbitarray.h:13
\inmodule QtBluetooth
\inmodule QtBluetooth
MajorDeviceClass
This enum describes a Bluetooth device's major device class.
\inmodule QtBluetooth
\inmodule QtCore
Definition qhash.h:820
\inmodule QtCore
\inmodule QtCore
\inmodule QtCore
Definition qobject.h:103
iterator find(const T &value)
Definition qset.h:159
\macro QT_RESTRICTED_CAST_FROM_ASCII
Definition qstring.h:129
bool isEmpty() const noexcept
Returns true if the string has no characters; otherwise returns false.
Definition qstring.h:192
static QString fromUtf8(QByteArrayView utf8)
This is an overloaded member function, provided for convenience. It differs from the above function o...
Definition qstring.cpp:6018
static QBitArray initializeMinorCaches()
static const char javaBluetoothClassDeviceClassName[]
static constexpr quint8 minorIndexSizes[]
static const char javaDeviceTypeLE[]
static const char javaDeviceTypeDual[]
QHash< jint, QBluetoothDeviceInfo::MajorDeviceClass > JCachedMajorTypes
static constexpr MajorClassJavaToQtMapping majorMappings[]
QHash< jint, quint8 > JCachedMinorTypes
static const char javaDeviceTypeUnknown[]
int mappingIndexForMajor(QBluetoothDeviceInfo::MajorDeviceClass major)
static const char javaDeviceTypeClassic[]
QBluetoothDeviceInfo::MajorDeviceClass resolveAndroidMajorClass(jint javaType)
static const char javaBluetoothClassDeviceMajorClassName[]
quint8 resolveAndroidMinorClass(QBluetoothDeviceInfo::MajorDeviceClass major, jint javaMinor)
QT_BEGIN_NAMESPACE typedef QHash< jint, QBluetoothDeviceInfo::CoreConfigurations > JCachedBtTypes
static const MinorClassJavaToQtMapping minorMappings[]
void triggerCachingOfMinorsForMajor(QBluetoothDeviceInfo::MajorDeviceClass major)
QBluetoothDeviceInfo::CoreConfigurations qtBtTypeForJavaBtType(jint javaType)
QSet< QString >::iterator it
QString valueForStaticField()
@ ExtraDevice
@ ExtraRssi
@ ActionFound
@ ActionDiscoveryStarted
@ ActionDiscoveryFinished
Combined button and popup list for selecting options.
static void * context
typedef QByteArray(EGLAPIENTRYP PFNQGSGETDISPLAYSPROC)()
#define Q_GLOBAL_STATIC_WITH_ARGS(TYPE, NAME, ARGS)
#define Q_GLOBAL_STATIC(TYPE, NAME,...)
#define qCWarning(category,...)
#define qCDebug(category,...)
#define Q_DECLARE_LOGGING_CATEGORY(name)
GLuint GLuint end
GLuint64EXT * result
[6]
#define Q_ASSERT(cond)
Definition qrandom.cpp:47
#define emit
#define Q_UNUSED(x)
unsigned int quint32
Definition qtypes.h:50
ptrdiff_t qsizetype
Definition qtypes.h:165
unsigned char quint8
Definition qtypes.h:46
QBitArray().isNull()
[3]
QAction * at
QHostInfo info
[0]
char * toString(const MyType &t)
[31]
QBluetoothDeviceInfo::MajorDeviceClass qtMajor