diff options
author | Juha Vuolle <juha.vuolle@insta.fi> | 2022-01-25 09:40:53 +0200 |
---|---|---|
committer | Qt Cherry-pick Bot <cherrypick_bot@qt-project.org> | 2022-01-27 17:19:41 +0000 |
commit | 228d5bad4b2aabf93c30393de706cad4d1424f68 (patch) | |
tree | c6518e01601be72bf631a843c165091041f49c1f | |
parent | e2f13481ee7ea479f0b7c20d61afd833cc6861e1 (diff) | |
download | qtconnectivity-228d5bad4b2aabf93c30393de706cad4d1424f68.tar.gz |
Make Windows bluetooth to scan all found devices for services
The service scan is split in two phases. First we discover the available
devices and then we scan each discovered device for their services.
The problem was that the Windows bluetooth backend scanned only the
device that was discovered the last and then stopped. This patch
addresses this by making the scanning logic to follow that of the
other backends (Bluez, macOS, and Android).
The change required also some adjustments to the stop() logic where
the Windows backend did not send the canceled() signal. The worker
"cancel logic" is nonexistent and does not produce the signal. A related
issue was that the stop() function is called both by
the baseclass and the windows specialization itself for slightly differing
purposes => needed to be split in two: releaseWorker() and stop().
Fixes: QTBUG-99687
Change-Id: Ie9e25cf0261c5259125dd0f4c6305ef1a99051e7
Reviewed-by: Qt CI Bot <qt_ci_bot@qt-project.org>
Reviewed-by: Ivan Solovev <ivan.solovev@qt.io>
(cherry picked from commit 30390a1285c631b766d98fc8dd79d9d9ec6a5eb0)
Reviewed-by: Qt Cherry-pick Bot <cherrypick_bot@qt-project.org>
3 files changed, 49 insertions, 39 deletions
diff --git a/src/bluetooth/qbluetoothservicediscoveryagent_p.h b/src/bluetooth/qbluetoothservicediscoveryagent_p.h index 32ef3cb2..d163a80c 100644 --- a/src/bluetooth/qbluetoothservicediscoveryagent_p.h +++ b/src/bluetooth/qbluetoothservicediscoveryagent_p.h @@ -239,10 +239,10 @@ private: private slots: void processFoundService(quint64 deviceAddress, const QBluetoothServiceInfo &info); void onScanFinished(quint64 deviceAddress); - void onScanCanceled(); void onError(); private: + void releaseWorker(); QPointer<QWinRTBluetoothServiceDiscoveryWorker> worker; #endif diff --git a/src/bluetooth/qbluetoothservicediscoveryagent_winrt.cpp b/src/bluetooth/qbluetoothservicediscoveryagent_winrt.cpp index b4594f21..5ca3382a 100644 --- a/src/bluetooth/qbluetoothservicediscoveryagent_winrt.cpp +++ b/src/bluetooth/qbluetoothservicediscoveryagent_winrt.cpp @@ -94,7 +94,6 @@ public: Q_SIGNALS: void serviceFound(quint64 deviceAddress, const QBluetoothServiceInfo &info); void scanFinished(quint64 deviceAddress); - void scanCanceled(); void errorOccured(); private: @@ -494,7 +493,7 @@ QBluetoothServiceDiscoveryAgentPrivate::QBluetoothServiceDiscoveryAgentPrivate( QBluetoothServiceDiscoveryAgentPrivate::~QBluetoothServiceDiscoveryAgentPrivate() { - stop(); + releaseWorker(); } void QBluetoothServiceDiscoveryAgentPrivate::start(const QBluetoothAddress &address) @@ -508,8 +507,6 @@ void QBluetoothServiceDiscoveryAgentPrivate::start(const QBluetoothAddress &addr this, &QBluetoothServiceDiscoveryAgentPrivate::processFoundService, Qt::QueuedConnection); connect(worker, &QWinRTBluetoothServiceDiscoveryWorker::scanFinished, this, &QBluetoothServiceDiscoveryAgentPrivate::onScanFinished, Qt::QueuedConnection); - connect(worker, &QWinRTBluetoothServiceDiscoveryWorker::scanCanceled, - this, &QBluetoothServiceDiscoveryAgentPrivate::onScanCanceled, Qt::QueuedConnection); connect(worker, &QWinRTBluetoothServiceDiscoveryWorker::errorOccured, this, &QBluetoothServiceDiscoveryAgentPrivate::onError, Qt::QueuedConnection); worker->start(); @@ -517,20 +514,9 @@ void QBluetoothServiceDiscoveryAgentPrivate::start(const QBluetoothAddress &addr void QBluetoothServiceDiscoveryAgentPrivate::stop() { - if (!worker) - return; - - disconnect(worker, &QWinRTBluetoothServiceDiscoveryWorker::serviceFound, - this, &QBluetoothServiceDiscoveryAgentPrivate::processFoundService); - disconnect(worker, &QWinRTBluetoothServiceDiscoveryWorker::scanFinished, - this, &QBluetoothServiceDiscoveryAgentPrivate::onScanFinished); - disconnect(worker, &QWinRTBluetoothServiceDiscoveryWorker::scanCanceled, - this, &QBluetoothServiceDiscoveryAgentPrivate::onScanCanceled); - disconnect(worker, &QWinRTBluetoothServiceDiscoveryWorker::errorOccured, - this, &QBluetoothServiceDiscoveryAgentPrivate::onError); - // mWorker will delete itself as soon as it is done with its discovery - worker = nullptr; - setDiscoveryState(Inactive); + releaseWorker(); + Q_Q(QBluetoothServiceDiscoveryAgent); + emit q->canceled(); } void QBluetoothServiceDiscoveryAgentPrivate::processFoundService(quint64 deviceAddress, const QBluetoothServiceInfo &info) @@ -579,26 +565,12 @@ void QBluetoothServiceDiscoveryAgentPrivate::processFoundService(quint64 deviceA void QBluetoothServiceDiscoveryAgentPrivate::onScanFinished(quint64 deviceAddress) { - Q_Q(QBluetoothServiceDiscoveryAgent); - bool deviceFound; - for (const QBluetoothDeviceInfo &deviceInfo : qAsConst(discoveredDevices)) { - if (deviceInfo.address().toUInt64() == deviceAddress) { - deviceFound = true; - discoveredDevices.removeOne(deviceInfo); - if (discoveredDevices.isEmpty()) - setDiscoveryState(Inactive); - break; - } - } - Q_ASSERT(deviceFound); - stop(); - emit q->finished(); -} - -void QBluetoothServiceDiscoveryAgentPrivate::onScanCanceled() -{ - Q_Q(QBluetoothServiceDiscoveryAgent); - emit q->canceled(); + // The scan for a device's services has finished. Disconnect the + // worker and call the baseclass function which starts the scan for + // the next device if there are any unscanned devices left (or finishes + // the scan if none left) + releaseWorker(); + _q_serviceDiscoveryFinished(); } void QBluetoothServiceDiscoveryAgentPrivate::onError() @@ -610,6 +582,21 @@ void QBluetoothServiceDiscoveryAgentPrivate::onError() emit q->error(error); } +void QBluetoothServiceDiscoveryAgentPrivate::releaseWorker() +{ + if (!worker) + return; + + disconnect(worker, &QWinRTBluetoothServiceDiscoveryWorker::serviceFound, + this, &QBluetoothServiceDiscoveryAgentPrivate::processFoundService); + disconnect(worker, &QWinRTBluetoothServiceDiscoveryWorker::scanFinished, + this, &QBluetoothServiceDiscoveryAgentPrivate::onScanFinished); + disconnect(worker, &QWinRTBluetoothServiceDiscoveryWorker::errorOccured, + this, &QBluetoothServiceDiscoveryAgentPrivate::onError); + // mWorker will delete itself as soon as it is done with its discovery + worker = nullptr; +} + QT_END_NAMESPACE #include <qbluetoothservicediscoveryagent_winrt.moc> diff --git a/tests/auto/qbluetoothservicediscoveryagent/tst_qbluetoothservicediscoveryagent.cpp b/tests/auto/qbluetoothservicediscoveryagent/tst_qbluetoothservicediscoveryagent.cpp index 94a065bc..52a0c8bd 100644 --- a/tests/auto/qbluetoothservicediscoveryagent/tst_qbluetoothservicediscoveryagent.cpp +++ b/tests/auto/qbluetoothservicediscoveryagent/tst_qbluetoothservicediscoveryagent.cpp @@ -64,6 +64,7 @@ private slots: void tst_invalidBtAddress(); void tst_serviceDiscovery_data(); void tst_serviceDiscovery(); + void tst_serviceDiscoveryStop(); void tst_serviceDiscoveryAdapters(); private: @@ -141,6 +142,28 @@ void tst_QBluetoothServiceDiscoveryAgent::initTestCase() } } +void tst_QBluetoothServiceDiscoveryAgent::tst_serviceDiscoveryStop() +{ + if (!localDeviceAvailable) + QSKIP("This test requires Bluetooth adapter in powered ON state"); + + QBluetoothServiceDiscoveryAgent discoveryAgent; + QSignalSpy finishedSpy(&discoveryAgent, SIGNAL(finished())); + QSignalSpy canceledSpy(&discoveryAgent, SIGNAL(canceled())); + + // Verify we get the correct signals on start-stop + discoveryAgent.start(QBluetoothServiceDiscoveryAgent::FullDiscovery); + QVERIFY(discoveryAgent.isActive()); + discoveryAgent.stop(); + QTRY_COMPARE(canceledSpy.count(), 1); + QVERIFY(!discoveryAgent.isActive()); + // Wait a bit to see that there are no latent signals + QTest::qWait(200); + QCOMPARE(canceledSpy.count(), 1); + QCOMPARE(finishedSpy.count(), 0); +} + + void tst_QBluetoothServiceDiscoveryAgent::tst_invalidBtAddress() { #ifdef Q_OS_OSX |