diff options
author | Ivan Solovev <ivan.solovev@qt.io> | 2021-09-14 16:15:01 +0200 |
---|---|---|
committer | Ivan Solovev <ivan.solovev@qt.io> | 2021-09-21 10:06:18 +0200 |
commit | 5beb4a8d37ae72abf801d20f04870f3f0652d89c (patch) | |
tree | 760b2a3cb3612c4f838757913a6b3c9b326689a5 | |
parent | 4af45b1256b92880c1a7d04d16d732eef1bee2b9 (diff) |
winrt: Protect from late AdvertisementReceived callback
This commit amends 83a845aa0e5bb155fae3f1d5d27bb80801f90935.
The callback can be called after the worker was deleted.
Task-number: QTBUG-96057
Change-Id: Ifbd58b240667bd5ff805b4250cf98a9fd2f96e90
Reviewed-by: Alex Blasche <alexander.blasche@qt.io>
(cherry picked from commit 3573702aa81f3f7ea20e947dbd27c5d1122cc42a)
Reviewed-by: Qt CI Bot <qt_ci_bot@qt-project.org>
-rw-r--r-- | src/bluetooth/qbluetoothdevicediscoveryagent_winrt.cpp | 206 |
1 files changed, 109 insertions, 97 deletions
diff --git a/src/bluetooth/qbluetoothdevicediscoveryagent_winrt.cpp b/src/bluetooth/qbluetoothdevicediscoveryagent_winrt.cpp index a64f7f0f..e515d4e1 100644 --- a/src/bluetooth/qbluetoothdevicediscoveryagent_winrt.cpp +++ b/src/bluetooth/qbluetoothdevicediscoveryagent_winrt.cpp @@ -155,6 +155,7 @@ private: #if QT_CONFIG(winrt_btle_no_pairing) HRESULT onBluetoothLEDeviceFound(ComPtr<IBluetoothLEDevice> device); #endif + HRESULT onBluetoothLEAdvertisementReceived(IBluetoothLEAdvertisementReceivedEventArgs *args); public slots: void finishDiscovery(); @@ -334,113 +335,74 @@ void QWinRTBluetoothDeviceDiscoveryWorker::gatherMultipleDeviceInformation(quint } } -void QWinRTBluetoothDeviceDiscoveryWorker::setupLEDeviceWatcher() +HRESULT QWinRTBluetoothDeviceDiscoveryWorker::onBluetoothLEAdvertisementReceived(IBluetoothLEAdvertisementReceivedEventArgs *args) { - HRESULT hr = RoActivateInstance(HString::MakeReference(RuntimeClass_Windows_Devices_Bluetooth_Advertisement_BluetoothLEAdvertisementWatcher).Get(), &m_leWatcher); - EMIT_WORKER_ERROR_AND_RETURN_IF_FAILED("Could not create advertisment watcher", - QBluetoothDeviceDiscoveryAgent::Error::UnknownError, - return); + quint64 address; + HRESULT hr; + hr = args->get_BluetoothAddress(&address); + EMIT_WORKER_ERROR_AND_RETURN_IF_FAILED("Could not obtain bluetooth address", + QBluetoothDeviceDiscoveryAgent::Error::UnknownError, + return S_OK); + qint16 rssi; + hr = args->get_RawSignalStrengthInDBm(&rssi); + EMIT_WORKER_ERROR_AND_RETURN_IF_FAILED("Could not obtain signal strength", + QBluetoothDeviceDiscoveryAgent::Error::UnknownError, + return S_OK); + ComPtr<IBluetoothLEAdvertisement> ad; + hr = args->get_Advertisement(&ad); + EMIT_WORKER_ERROR_AND_RETURN_IF_FAILED("Could get advertisement", + QBluetoothDeviceDiscoveryAgent::Error::UnknownError, + return S_OK); + const ManufacturerData manufacturerData = extractManufacturerData(ad); + QBluetoothDeviceInfo::Fields changedFields = QBluetoothDeviceInfo::Field::None; + if (!m_foundLEManufacturerData.contains(address)) { + m_foundLEManufacturerData.insert(address, manufacturerData); + changedFields.setFlag(QBluetoothDeviceInfo::Field::ManufacturerData); + } else if (m_foundLEManufacturerData.value(address) != manufacturerData) { + m_foundLEManufacturerData[address] = manufacturerData; + changedFields.setFlag(QBluetoothDeviceInfo::Field::ManufacturerData); + } #if QT_CONFIG(winrt_btle_no_pairing) if (supportsNewLEApi()) { - hr = m_leWatcher->put_ScanningMode(BluetoothLEScanningMode_Active); - EMIT_WORKER_ERROR_AND_RETURN_IF_FAILED("Could not set scanning mode", - QBluetoothDeviceDiscoveryAgent::Error::UnknownError, - return); - } -#endif // winrt_btle_no_pairing - hr = m_leWatcher->add_Received(Callback<ITypedEventHandler<BluetoothLEAdvertisementWatcher *, BluetoothLEAdvertisementReceivedEventArgs *>>([this](IBluetoothLEAdvertisementWatcher *, IBluetoothLEAdvertisementReceivedEventArgs *args) { - quint64 address; - HRESULT hr; - hr = args->get_BluetoothAddress(&address); - EMIT_WORKER_ERROR_AND_RETURN_IF_FAILED("Could not obtain bluetooth address", - QBluetoothDeviceDiscoveryAgent::Error::UnknownError, - return S_OK); - qint16 rssi; - hr = args->get_RawSignalStrengthInDBm(&rssi); - EMIT_WORKER_ERROR_AND_RETURN_IF_FAILED("Could not obtain signal strength", + ComPtr<IVector<GUID>> guids; + hr = ad->get_ServiceUuids(&guids); + EMIT_WORKER_ERROR_AND_RETURN_IF_FAILED("Could not obtain service uuid list", QBluetoothDeviceDiscoveryAgent::Error::UnknownError, return S_OK); - ComPtr<IBluetoothLEAdvertisement> ad; - hr = args->get_Advertisement(&ad); - EMIT_WORKER_ERROR_AND_RETURN_IF_FAILED("Could get advertisement", + quint32 size; + hr = guids->get_Size(&size); + EMIT_WORKER_ERROR_AND_RETURN_IF_FAILED("Could not obtain service uuid list size", QBluetoothDeviceDiscoveryAgent::Error::UnknownError, return S_OK); - const ManufacturerData manufacturerData = extractManufacturerData(ad); - QBluetoothDeviceInfo::Fields changedFields = QBluetoothDeviceInfo::Field::None; - if (!m_foundLEManufacturerData.contains(address)) { - m_foundLEManufacturerData.insert(address, manufacturerData); - changedFields.setFlag(QBluetoothDeviceInfo::Field::ManufacturerData); - } else if (m_foundLEManufacturerData.value(address) != manufacturerData) { - m_foundLEManufacturerData[address] = manufacturerData; - changedFields.setFlag(QBluetoothDeviceInfo::Field::ManufacturerData); - } -#if QT_CONFIG(winrt_btle_no_pairing) - if (supportsNewLEApi()) { - ComPtr<IVector<GUID>> guids; - hr = ad->get_ServiceUuids(&guids); - EMIT_WORKER_ERROR_AND_RETURN_IF_FAILED("Could not obtain service uuid list", - QBluetoothDeviceDiscoveryAgent::Error::UnknownError, - return S_OK); - quint32 size; - hr = guids->get_Size(&size); - QVector<QBluetoothUuid> serviceUuids; - EMIT_WORKER_ERROR_AND_RETURN_IF_FAILED("Could not obtain service uuid list size", + QVector<QBluetoothUuid> serviceUuids; + for (quint32 i = 0; i < size; ++i) { + GUID guid; + hr = guids->GetAt(i, &guid); + EMIT_WORKER_ERROR_AND_RETURN_IF_FAILED("Could not obtain uuid", QBluetoothDeviceDiscoveryAgent::Error::UnknownError, return S_OK); - for (quint32 i = 0; i < size; ++i) { - GUID guid; - hr = guids->GetAt(i, &guid); - EMIT_WORKER_ERROR_AND_RETURN_IF_FAILED("Could not obtain uuid", - QBluetoothDeviceDiscoveryAgent::Error::UnknownError, - return S_OK); - QBluetoothUuid uuid(guid); - serviceUuids.append(uuid); + QBluetoothUuid uuid(guid); + serviceUuids.append(uuid); + } + QMutexLocker locker(&m_foundDevicesMutex); + // Merge newly found services with list of currently found ones + if (m_foundLEDevicesMap.contains(address)) { + if (size == 0) + return S_OK; + const LEAdvertisingInfo adInfo = m_foundLEDevicesMap.value(address); + QVector<QBluetoothUuid> foundServices = adInfo.services; + if (adInfo.rssi != rssi) { + m_foundLEDevicesMap[address].rssi = rssi; + changedFields.setFlag(QBluetoothDeviceInfo::Field::RSSI); } - QMutexLocker locker(&m_foundDevicesMutex); - // Merge newly found services with list of currently found ones - if (m_foundLEDevicesMap.contains(address)) { - if (size == 0) - return S_OK; - const LEAdvertisingInfo adInfo = m_foundLEDevicesMap.value(address); - QVector<QBluetoothUuid> foundServices = adInfo.services; - if (adInfo.rssi != rssi) { - m_foundLEDevicesMap[address].rssi = rssi; - changedFields.setFlag(QBluetoothDeviceInfo::Field::RSSI); - } - bool newServiceAdded = false; - for (const QBluetoothUuid &uuid : qAsConst(serviceUuids)) { - if (!foundServices.contains(uuid)) { - foundServices.append(uuid); - newServiceAdded = true; - } + bool newServiceAdded = false; + for (const QBluetoothUuid &uuid : qAsConst(serviceUuids)) { + if (!foundServices.contains(uuid)) { + foundServices.append(uuid); + newServiceAdded = true; } - if (!newServiceAdded) { - if (!changedFields.testFlag(QBluetoothDeviceInfo::Field::None)) { - QMetaObject::invokeMethod(this, "deviceDataChanged", Qt::AutoConnection, - Q_ARG(QBluetoothAddress, QBluetoothAddress(address)), - Q_ARG(QBluetoothDeviceInfo::Fields, changedFields), - Q_ARG(qint16, rssi), - Q_ARG(ManufacturerData, manufacturerData)); - } - return S_OK; - } - m_foundLEDevicesMap[address].services = foundServices; - } else { - LEAdvertisingInfo info; - info.services = std::move(serviceUuids); - info.rssi = rssi; - m_foundLEDevicesMap.insert(address, info); } - - locker.unlock(); - } else -#endif - { - if (m_foundLEDevices.contains(address)) { - if (m_foundLEDevices.value(address) != rssi) { - m_foundLEDevices[address] = rssi; - changedFields.setFlag(QBluetoothDeviceInfo::Field::RSSI); - } + if (!newServiceAdded) { if (!changedFields.testFlag(QBluetoothDeviceInfo::Field::None)) { QMetaObject::invokeMethod(this, "deviceDataChanged", Qt::AutoConnection, Q_ARG(QBluetoothAddress, QBluetoothAddress(address)), @@ -450,9 +412,59 @@ void QWinRTBluetoothDeviceDiscoveryWorker::setupLEDeviceWatcher() } return S_OK; } - m_foundLEDevices.insert(address, rssi); + m_foundLEDevicesMap[address].services = foundServices; + } else { + LEAdvertisingInfo info; + info.services = std::move(serviceUuids); + info.rssi = rssi; + m_foundLEDevicesMap.insert(address, info); + } + + locker.unlock(); + } else +#endif // QT_CONFIG(winrt_btle_no_pairing) + { + if (m_foundLEDevices.contains(address)) { + if (m_foundLEDevices.value(address) != rssi) { + m_foundLEDevices[address] = rssi; + changedFields.setFlag(QBluetoothDeviceInfo::Field::RSSI); + } + if (!changedFields.testFlag(QBluetoothDeviceInfo::Field::None)) { + QMetaObject::invokeMethod(this, "deviceDataChanged", Qt::AutoConnection, + Q_ARG(QBluetoothAddress, QBluetoothAddress(address)), + Q_ARG(QBluetoothDeviceInfo::Fields, changedFields), + Q_ARG(qint16, rssi), + Q_ARG(ManufacturerData, manufacturerData)); + } + return S_OK; } - leBluetoothInfoFromAddressAsync(address); + m_foundLEDevices.insert(address, rssi); + } + leBluetoothInfoFromAddressAsync(address); + return S_OK; +} + +void QWinRTBluetoothDeviceDiscoveryWorker::setupLEDeviceWatcher() +{ + HRESULT hr = RoActivateInstance(HString::MakeReference(RuntimeClass_Windows_Devices_Bluetooth_Advertisement_BluetoothLEAdvertisementWatcher).Get(), &m_leWatcher); + EMIT_WORKER_ERROR_AND_RETURN_IF_FAILED("Could not create advertisment watcher", + QBluetoothDeviceDiscoveryAgent::Error::UnknownError, + return); +#if QT_CONFIG(winrt_btle_no_pairing) + if (supportsNewLEApi()) { + hr = m_leWatcher->put_ScanningMode(BluetoothLEScanningMode_Active); + EMIT_WORKER_ERROR_AND_RETURN_IF_FAILED("Could not set scanning mode", + QBluetoothDeviceDiscoveryAgent::Error::UnknownError, + return); + } +#endif // QT_CONFIG(winrt_btle_no_pairing) + QPointer<QWinRTBluetoothDeviceDiscoveryWorker> thisPointer(this); + hr = m_leWatcher->add_Received( + Callback<ITypedEventHandler<BluetoothLEAdvertisementWatcher *, BluetoothLEAdvertisementReceivedEventArgs *>>( + [thisPointer](IBluetoothLEAdvertisementWatcher *, IBluetoothLEAdvertisementReceivedEventArgs *args) { + if (thisPointer) + return thisPointer->onBluetoothLEAdvertisementReceived(args); + return S_OK; }).Get(), &m_leDeviceAddedToken); EMIT_WORKER_ERROR_AND_RETURN_IF_FAILED("Could not add device callback", |