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>
31 const qsizetype numberOfMajorDeviceClasses = 11;
49 qCWarning(QT_BT_ANDROID) <<
"Unknown category of major device class:" << classes;
52 return QBitArray(numberOfMajorDeviceClasses,
false);
59static const
char javaBluetoothDeviceClassName[] = "android/bluetooth/BluetoothDevice";
71 const char javaFieldName[14];
226 const JCachedBtTypes::iterator
it = cachedBtTypes()->
find(javaType);
227 if (
it == cachedBtTypes()->
end()) {
229 if (javaType == QJniObject::getStaticField<jint>(
231 cachedBtTypes()->insert(javaType,
234 }
else if (javaType == QJniObject::getStaticField<jint>(
236 cachedBtTypes()->insert(javaType,
239 }
else if (javaType == QJniObject::getStaticField<jint>(
241 cachedBtTypes()->insert(javaType,
244 }
else if (javaType == QJniObject::getStaticField<jint>(
246 cachedBtTypes()->insert(javaType,
249 qCWarning(QT_BT_ANDROID) <<
"Unknown Bluetooth device type value";
260 const JCachedMajorTypes::iterator
it = cachedMajorTypes()->
find(javaType);
261 if (
it == cachedMajorTypes()->
end()) {
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;
277 cachedMajorTypes()->insert(fieldValue, majorMapping.qtMajor);
280 if (fieldValue == javaType)
281 result = majorMapping.qtMajor;
296 int mappingIndex = (int) major;
315 jint fieldValue = QJniObject::getStaticField<jint>(
319 cachedMinorTypes()->insert(fieldValue,
minorMappings[sizeIndex].qtMinor);
323 initializedCacheTracker()->setBit(mappingIndex);
337 if (!initializedCacheTracker()->
at(mappingIndex))
340 const JCachedMinorTypes::iterator
it = cachedMinorTypes()->
find(javaMinor);
341 if (
it == cachedMinorTypes()->
end())
351 valueForStaticField<QtJniTypes::BluetoothDevice, JavaNames::ActionFound>()));
353 valueForStaticField<QtJniTypes::BluetoothAdapter, JavaNames::ActionDiscoveryStarted>()));
355 valueForStaticField<QtJniTypes::BluetoothAdapter, JavaNames::ActionDiscoveryFinished>()));
365 const QString action = intentObject.callMethod<jstring>(
"getAction").
toString();
367 qCDebug(QT_BT_ANDROID) <<
"DeviceDiscoveryBroadcastReceiver::onReceive() - event:" << action;
382 intentObject.callMethod<QtJniTypes::Parcelable>(
"getParcelableExtra",
383 keyExtra.object<jstring>());
385 if (!bluetoothDevice.isValid())
390 int rssi = intentObject.callMethod<jshort>(
"getShortExtra",
391 keyExtra.object<jstring>(), jshort(0));
401 JNIEnv *, jobject jBluetoothDevice, jint
rssi, jbyteArray scanRecord)
403 const QJniObject bluetoothDevice(jBluetoothDevice);
404 if (!bluetoothDevice.isValid())
414 const QString deviceName = bluetoothDevice.callMethod<jstring>(
"getName").
toString();
416 bluetoothDevice.callMethod<jstring>(
"getAddress").toString());
418 bluetoothDevice.callMethod<QtJniTypes::BluetoothClass>(
"getBluetoothClass");
420 if (!bluetoothClass.isValid())
424 bluetoothClass.callMethod<jint>(
"getMajorDeviceClass"));
428 jint javaMinor = bluetoothClass.callMethod<jint>(
"getDeviceClass");
432 classType |= ((
quint32(minorDeviceType) & 0x3f) << 2);
448 int androidId = (current << 16);
449 if (bluetoothClass.callMethod<jboolean>(
"hasService", androidId))
450 serviceResult |= current;
454 classType |= (serviceResult << 13);
459 if (scanRecord !=
nullptr) {
462 jbyte *elems = env->GetByteArrayElements(scanRecord, &isCopy);
463 const char *scanRecordBuffer =
reinterpret_cast<const char *
>(elems);
464 const jsize scanRecordLength = env->GetArrayLength(scanRecord);
466 QList<QBluetoothUuid> serviceUuids;
471 while (
i < scanRecordLength) {
475 const int nBytes = scanRecordBuffer[
i];
479 if (
i >= scanRecordLength - nBytes)
482 const int adType = scanRecordBuffer[
i+1];
483 const char *dataPtr = &scanRecordBuffer[
i+2];
489 foundService =
QBluetoothUuid(qFromLittleEndian<quint16>(dataPtr));
493 foundService =
QBluetoothUuid(qFromLittleEndian<quint32>(dataPtr));
498 QBluetoothUuid(qToBigEndian<QUuid::Id128Bytes>(qFromLittleEndian<QUuid::Id128Bytes>(dataPtr)));
515 qFromLittleEndian<QUuid::Id128Bytes>(dataPtr))),
521 info.setManufacturerData(qFromLittleEndian<quint16>(dataPtr),
543 if (!foundService.isNull() && !serviceUuids.contains(foundService))
544 serviceUuids.append(foundService);
547 if (
info.name().isEmpty())
548 info.setName(localName);
550 info.setServiceUuids(serviceUuids);
552 env->ReleaseByteArrayElements(scanRecord, elems, JNI_ABORT);
555 auto methodId = env.findMethod(bluetoothDevice.objectClass(),
"getType",
"()I");
556 jint javaBtType = env->CallIntMethod(bluetoothDevice.object(), methodId);
557 if (!env.checkAndClearExceptions()) {
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)
DeviceDiscoveryBroadcastReceiver(QObject *parent=nullptr)
void deviceDiscovered(const QBluetoothDeviceInfo &info, bool isLeScanResult)
@ WiredModemOrVoiceGatewayPhone
@ UncategorizedWearableDevice
@ UncategorizedHealthDevice
@ HealthBloodPressureMonitor
@ KeyboardWithPointingDevicePeripheral
@ UncategorizedPeripheral
@ PointingDevicePeripheral
@ BaseRateAndLowEnergyCoreConfiguration
@ LowEnergyCoreConfiguration
@ UnknownCoreConfiguration
@ BaseRateCoreConfiguration
MajorDeviceClass
This enum describes a Bluetooth device's major device class.
@ HandheldClamShellComputer
@ UncategorizedAudioVideoDevice
@ VideoDisplayAndLoudspeaker
iterator find(const T &value)
\macro QT_RESTRICTED_CAST_FROM_ASCII
bool isEmpty() const noexcept
Returns true if the string has no characters; otherwise returns false.
static QString fromUtf8(QByteArrayView utf8)
This is an overloaded member function, provided for convenience. It differs from the above function o...
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[]
@ ADType16BitUuidComplete
@ ADTypeShortenedLocalName
@ ADType32BitUuidIncomplete
@ ADTypeManufacturerSpecificData
@ ADType128BitUuidIncomplete
@ ADType16BitUuidIncomplete
@ ADTypeCompleteLocalName
@ ADType32BitUuidComplete
@ ADType128BitUuidComplete
@ ADTypeServiceData128Bit
void triggerCachingOfMinorsForMajor(QBluetoothDeviceInfo::MajorDeviceClass major)
QBluetoothDeviceInfo::CoreConfigurations qtBtTypeForJavaBtType(jint javaType)
QSet< QString >::iterator it
QString valueForStaticField()
@ ActionDiscoveryFinished
Combined button and popup list for selecting options.
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)
char * toString(const MyType &t)
[31]
QBluetoothDeviceInfo::MajorDeviceClass qtMajor
char const * javaFieldName