Qt 6.x
The Qt SDK
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
88};
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
107{
108 char const * javaFieldName;
110};
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*/
208enum ADType {
221 // .. more will be added when required
222};
223
224// Endianness conversion for QUuid::Id128Bytes doesn't exist in qtendian.h
226{
228 for (int i = 0; i < 16; i++)
229 dst.data[i] = src.data[15 - i];
230 return dst;
231}
232
233QBluetoothDeviceInfo::CoreConfigurations qtBtTypeForJavaBtType(jint javaType)
234{
235 const JCachedBtTypes::iterator it = cachedBtTypes()->find(javaType);
236 if (it == cachedBtTypes()->end()) {
237
238 if (javaType == QJniObject::getStaticField<jint>(
239 javaBluetoothDeviceClassName, javaDeviceTypeClassic)) {
240 cachedBtTypes()->insert(javaType,
243 } else if (javaType == QJniObject::getStaticField<jint>(
244 javaBluetoothDeviceClassName, javaDeviceTypeLE)) {
245 cachedBtTypes()->insert(javaType,
248 } else if (javaType == QJniObject::getStaticField<jint>(
249 javaBluetoothDeviceClassName, javaDeviceTypeDual)) {
250 cachedBtTypes()->insert(javaType,
253 } else if (javaType == QJniObject::getStaticField<jint>(
254 javaBluetoothDeviceClassName, javaDeviceTypeUnknown)) {
255 cachedBtTypes()->insert(javaType,
257 } else {
258 qCWarning(QT_BT_ANDROID) << "Unknown Bluetooth device type value";
259 }
260
262 } else {
263 return it.value();
264 }
265}
266
268{
269 const JCachedMajorTypes::iterator it = cachedMajorTypes()->find(javaType);
270 if (it == cachedMajorTypes()->end()) {
271 QJniEnvironment env;
272 // precache all major device class fields
273 jint fieldValue;
275 auto clazz = env->FindClass(javaBluetoothClassDeviceMajorClassName);
276 for (const auto &majorMapping : majorMappings) {
277 auto fieldId = env->GetStaticFieldID(clazz, majorMapping.javaFieldName, "I");
278 if (!env->ExceptionCheck())
279 fieldValue = env->GetStaticIntField(clazz, fieldId);
280 if (env.checkAndClearExceptions()) {
281 qCWarning(QT_BT_ANDROID) << "Unknown BluetoothClass.Device.Major field" << javaType;
282
283 // add fallback value because field not readable
284 cachedMajorTypes()->insert(javaType, QBluetoothDeviceInfo::UncategorizedDevice);
285 } else {
286 cachedMajorTypes()->insert(fieldValue, majorMapping.qtMajor);
287 }
288
289 if (fieldValue == javaType)
290 result = majorMapping.qtMajor;
291 }
292
293 return result;
294 } else {
295 return it.value();
296 }
297}
298
299/*
300 The index for major into the MinorClassJavaToQtMapping and initializedCacheTracker
301 is major+1 except for UncategorizedDevice which is at index 0.
302*/
304{
305 int mappingIndex = (int) major;
307 mappingIndex = 0;
308 else
309 mappingIndex++;
310
311 Q_ASSERT(mappingIndex >=0
312 && mappingIndex <= (QBluetoothDeviceInfo::HealthDevice + 1));
313
314 return mappingIndex;
315}
316
318{
319 //qCDebug(QT_BT_ANDROID) << "Caching minor values for major" << major;
320 int mappingIndex = mappingIndexForMajor(major);
321 quint8 sizeIndex = minorIndexSizes[mappingIndex];
322
323 while (minorMappings[sizeIndex].javaFieldName != nullptr) {
324 jint fieldValue = QJniObject::getStaticField<jint>(
325 javaBluetoothClassDeviceClassName, minorMappings[sizeIndex].javaFieldName);
326
327 Q_ASSERT(fieldValue >= 0);
328 cachedMinorTypes()->insert(fieldValue, minorMappings[sizeIndex].qtMinor);
329 sizeIndex++;
330 }
331
332 initializedCacheTracker()->setBit(mappingIndex);
333}
334
336{
337 // there are no minor device classes in java with value 0
338 //qCDebug(QT_BT_ANDROID) << "received minor class device:" << javaMinor;
339 if (javaMinor == 0)
340 return 0;
341
342 int mappingIndex = mappingIndexForMajor(major);
343
344 // whenever we encounter a not yet seen major device class
345 // we populate the cache with all its related minor values
346 if (!initializedCacheTracker()->at(mappingIndex))
348
349 const JCachedMinorTypes::iterator it = cachedMinorTypes()->find(javaMinor);
350 if (it == cachedMinorTypes()->end())
351 return 0;
352 else
353 return it.value();
354}
355
356
358{
359 addAction(valueForStaticField<QtJniTypes::BluetoothDevice, JavaNames::ActionFound>());
360 addAction(valueForStaticField<QtJniTypes::BluetoothAdapter, JavaNames::ActionDiscoveryStarted>());
361 addAction(valueForStaticField<QtJniTypes::BluetoothAdapter, JavaNames::ActionDiscoveryFinished>());
362}
363
364// Runs in Java thread
365void DeviceDiscoveryBroadcastReceiver::onReceive(JNIEnv *env, jobject context, jobject intent)
366{
368 Q_UNUSED(env)
369
370 QJniObject intentObject(intent);
371 const QString action = intentObject.callMethod<jstring>("getAction").toString();
372
373 qCDebug(QT_BT_ANDROID) << "DeviceDiscoveryBroadcastReceiver::onReceive() - event:" << action;
374
375 if (action == valueForStaticField<QtJniTypes::BluetoothAdapter,
377 emit finished();
378 } else if (action == valueForStaticField<QtJniTypes::BluetoothAdapter,
381 } else if (action == valueForStaticField<QtJniTypes::BluetoothDevice,
383 //get BluetoothDevice
384 QJniObject keyExtra = valueForStaticField<QtJniTypes::BluetoothDevice,
386 const QJniObject bluetoothDevice =
387 intentObject.callMethod<QtJniTypes::Parcelable>("getParcelableExtra",
388 keyExtra.object<jstring>());
389
390 if (!bluetoothDevice.isValid())
391 return;
392
393 keyExtra = valueForStaticField<QtJniTypes::BluetoothDevice,
395 int rssi = intentObject.callMethod<jshort>("getShortExtra",
396 keyExtra.object<jstring>(), jshort(0));
397
398 const QBluetoothDeviceInfo info = retrieveDeviceInfo(bluetoothDevice, rssi);
399 if (info.isValid())
400 emit deviceDiscovered(info, false);
401 }
402}
403
404// Runs in Java thread
406 JNIEnv */*env*/, jobject jBluetoothDevice, jint rssi, jbyteArray scanRecord)
407{
408 const QJniObject bluetoothDevice(jBluetoothDevice);
409 if (!bluetoothDevice.isValid())
410 return;
411
412 const QBluetoothDeviceInfo info = retrieveDeviceInfo(bluetoothDevice, rssi, scanRecord);
413 if (info.isValid())
415}
416
417QBluetoothDeviceInfo DeviceDiscoveryBroadcastReceiver::retrieveDeviceInfo(const QJniObject &bluetoothDevice, int rssi, jbyteArray scanRecord)
418{
419 const QString deviceName = bluetoothDevice.callMethod<jstring>("getName").toString();
420 const QBluetoothAddress deviceAddress(
421 bluetoothDevice.callMethod<jstring>("getAddress").toString());
422 const QJniObject bluetoothClass =
423 bluetoothDevice.callMethod<QtJniTypes::BluetoothClass>("getBluetoothClass");
424
425 if (!bluetoothClass.isValid())
426 return QBluetoothDeviceInfo();
427
429 bluetoothClass.callMethod<jint>("getMajorDeviceClass"));
430 // major device class is 5 bits from index 8 - 12
431 quint32 classType = ((quint32(majorClass) & 0x1f) << 8);
432
433 jint javaMinor = bluetoothClass.callMethod<jint>("getDeviceClass");
434 quint8 minorDeviceType = resolveAndroidMinorClass(majorClass, javaMinor);
435
436 // minor device class is 6 bits from index 2 - 7
437 classType |= ((quint32(minorDeviceType) & 0x3f) << 2);
438
439 static constexpr quint32 services[] = {
448 };
449
450 // Matching BluetoothClass.Service values
451 quint32 serviceResult = 0;
452 for (quint32 current : services) {
453 int androidId = (current << 16); // Android values shift by 2 bytes compared to Qt enums
454 if (bluetoothClass.callMethod<jboolean>("hasService", androidId))
455 serviceResult |= current;
456 }
457
458 // service class info is 11 bits from index 13 - 23
459 classType |= (serviceResult << 13);
460
461 QBluetoothDeviceInfo info(deviceAddress, deviceName, classType);
462 info.setRssi(rssi);
463 QJniEnvironment env;
464 if (scanRecord != nullptr) {
465 // Parse scan record
466 jboolean isCopy;
467 jbyte *elems = env->GetByteArrayElements(scanRecord, &isCopy);
468 const char *scanRecordBuffer = reinterpret_cast<const char *>(elems);
469 const jsize scanRecordLength = env->GetArrayLength(scanRecord);
470
471 QList<QBluetoothUuid> serviceUuids;
472 jsize i = 0;
473
474 // Spec 4.2, Vol 3, Part C, Chapter 11
475 QString localName;
476 while (i < scanRecordLength) {
477 // sizeof(EIR Data) = sizeof(Length) + sizeof(EIR data Type) + sizeof(EIR Data)
478 // Length = sizeof(EIR data Type) + sizeof(EIR Data)
479
480 const int nBytes = scanRecordBuffer[i];
481 if (nBytes == 0)
482 break;
483
484 if (i >= scanRecordLength - nBytes)
485 break;
486
487 const int adType = scanRecordBuffer[i+1];
488 const char *dataPtr = &scanRecordBuffer[i+2];
489 QBluetoothUuid foundService;
490
491 switch (adType) {
494 foundService = QBluetoothUuid(qFromLittleEndian<quint16>(dataPtr));
495 break;
498 foundService = QBluetoothUuid(qFromLittleEndian<quint32>(dataPtr));
499 break;
502 foundService =
503 QBluetoothUuid(qToBigEndian<QUuid::Id128Bytes>(qFromLittleEndian<QUuid::Id128Bytes>(dataPtr)));
504 break;
506 if (nBytes >= 3) {
507 info.setServiceData(QBluetoothUuid(qFromLittleEndian<quint16>(dataPtr)),
508 QByteArray(dataPtr + 2, nBytes - 3));
509 }
510 break;
512 if (nBytes >= 5) {
513 info.setServiceData(QBluetoothUuid(qFromLittleEndian<quint32>(dataPtr)),
514 QByteArray(dataPtr + 4, nBytes - 5));
515 }
516 break;
518 if (nBytes >= 17) {
519 info.setServiceData(QBluetoothUuid(qToBigEndian<QUuid::Id128Bytes>(
520 qFromLittleEndian<QUuid::Id128Bytes>(dataPtr))),
521 QByteArray(dataPtr + 16, nBytes - 17));
522 }
523 break;
525 if (nBytes >= 3) {
526 info.setManufacturerData(qFromLittleEndian<quint16>(dataPtr),
527 QByteArray(dataPtr + 2, nBytes - 3));
528 }
529 break;
530 // According to Spec 5.0, Vol 3, Part C, Chapter 12.1
531 // the device's local name is utf8 encoded
533 if (localName.isEmpty())
534 localName = QString::fromUtf8(dataPtr, nBytes - 1);
535 break;
537 localName = QString::fromUtf8(dataPtr, nBytes - 1);
538 break;
539 default:
540 // qWarning() << "Unhandled AD Type" << Qt::hex << adType;
541 // no other types supported yet and therefore skipped
542 // https://www.bluetooth.com/specifications/assigned-numbers/generic-access-profile
543 break;
544 }
545
546 i += nBytes + 1;
547
548 if (!foundService.isNull() && !serviceUuids.contains(foundService))
549 serviceUuids.append(foundService);
550 }
551
552 if (info.name().isEmpty())
553 info.setName(localName);
554
555 info.setServiceUuids(serviceUuids);
556
557 env->ReleaseByteArrayElements(scanRecord, elems, JNI_ABORT);
558 }
559
560 auto methodId = env.findMethod(bluetoothDevice.objectClass(), "getType", "()I");
561 jint javaBtType = env->CallIntMethod(bluetoothDevice.object(), methodId);
562 if (!env.checkAndClearExceptions()) {
563 info.setCoreConfigurations(qtBtTypeForJavaBtType(javaBtType));
564 }
565
566 return info;
567}
568
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 qbytearray.h:57
\inmodule QtCore
Definition qhash.h:1093
\inmodule QtCore
Definition qhash.h:818
\inmodule QtCore
\inmodule QtCore
Definition qlist.h:74
void append(parameter_type t)
Definition qlist.h:441
\inmodule QtCore
Definition qobject.h:90
iterator find(const T &value)
Definition qset.h:159
\macro QT_RESTRICTED_CAST_FROM_ASCII
Definition qstring.h:127
static QString fromUtf8(QByteArrayView utf8)
This is an overloaded member function, provided for convenience. It differs from the above function o...
Definition qstring.cpp:5857
bool isEmpty() const
Returns true if the string has no characters; otherwise returns false.
Definition qstring.h:1083
bool isNull() const noexcept
Returns true if this is the null UUID {00000000-0000-0000-0000-000000000000}; otherwise returns false...
Definition quuid.cpp:768
static QBitArray initializeMinorCaches()
static const char javaBluetoothClassDeviceClassName[]
static constexpr quint8 minorIndexSizes[]
static const char javaDeviceTypeLE[]
static const char javaDeviceTypeDual[]
static constexpr MajorClassJavaToQtMapping majorMappings[]
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
QUuid::Id128Bytes qbswap(const QUuid::Id128Bytes src)
static const MinorClassJavaToQtMapping minorMappings[]
void triggerCachingOfMinorsForMajor(QBluetoothDeviceInfo::MajorDeviceClass major)
QBluetoothDeviceInfo::CoreConfigurations qtBtTypeForJavaBtType(jint javaType)
QSet< QString >::iterator it
@ ExtraDevice
@ ExtraRssi
@ ActionFound
@ ActionDiscoveryStarted
@ ActionDiscoveryFinished
QJniObject valueForStaticField()
Combined button and popup list for selecting options.
static void * context
#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
GLenum src
GLenum GLenum dst
GLuint64EXT * result
[6]
#define Q_ASSERT(cond)
Definition qrandom.cpp:47
#define emit
#define Q_UNUSED(x)
unsigned int quint32
Definition qtypes.h:45
ptrdiff_t qsizetype
Definition qtypes.h:70
unsigned char quint8
Definition qtypes.h:41
QFileInfo info(fileName)
[8]
QAction * at
char * toString(const MyType &t)
[31]
QBluetoothDeviceInfo::MajorDeviceClass qtMajor
bool contains(const AT &t) const noexcept
Definition qlist.h:44
IUIAutomationTreeWalker __RPC__deref_out_opt IUIAutomationElement ** parent
\inmodule QtCore
Definition quuid.h:58