summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorIvan Solovev <ivan.solovev@qt.io>2022-07-13 12:11:15 +0200
committerIvan Solovev <ivan.solovev@qt.io>2022-07-19 10:41:24 +0200
commita8dd5a7c5b23b14bcfe074165b40c5c6b13d0ac1 (patch)
tree9e411d003decb8fce6d95027fc355d371e46db15
parent78149c7c26722c85b624dd4bc49942638e12b92c (diff)
Windows: refactor device discovery
- Move the LE scan timer to the worker class - Introduce a separate function to check for scan finish conditions. These changes allow us to be more precise in deciding when to stop device discovery. For example, before this change we were unconditionally stopping the discovery when the LE scan timeout expired, even if the Classic scan was still in progress. That is fixed now. Fixes: QTBUG-103263 Fixes: QTBUG-97797 Change-Id: I8ab457971b95a7573483b9e6f4e8abbec97e9755 Reviewed-by: Qt CI Bot <qt_ci_bot@qt-project.org> Reviewed-by: Juha Vuolle <juha.vuolle@insta.fi> Reviewed-by: Oliver Wolff <oliver.wolff@qt.io> (cherry picked from commit 9ab5122091a65936458c726270e693eca7a99277) Reviewed-by: Qt Cherry-pick Bot <cherrypick_bot@qt-project.org>
-rw-r--r--src/bluetooth/qbluetoothdevicediscoveryagent_p.h1
-rw-r--r--src/bluetooth/qbluetoothdevicediscoveryagent_winrt.cpp82
2 files changed, 47 insertions, 36 deletions
diff --git a/src/bluetooth/qbluetoothdevicediscoveryagent_p.h b/src/bluetooth/qbluetoothdevicediscoveryagent_p.h
index 7f88c6e0..34d62633 100644
--- a/src/bluetooth/qbluetoothdevicediscoveryagent_p.h
+++ b/src/bluetooth/qbluetoothdevicediscoveryagent_p.h
@@ -187,7 +187,6 @@ private slots:
private:
void disconnectAndClearWorker();
std::shared_ptr<QWinRTBluetoothDeviceDiscoveryWorker> worker = nullptr;
- QTimer *leScanTimer = nullptr;
#endif
#ifdef Q_OS_DARWIN
diff --git a/src/bluetooth/qbluetoothdevicediscoveryagent_winrt.cpp b/src/bluetooth/qbluetoothdevicediscoveryagent_winrt.cpp
index 263e1f13..c02eb5f3 100644
--- a/src/bluetooth/qbluetoothdevicediscoveryagent_winrt.cpp
+++ b/src/bluetooth/qbluetoothdevicediscoveryagent_winrt.cpp
@@ -231,9 +231,10 @@ class QWinRTBluetoothDeviceDiscoveryWorker : public QObject,
{
Q_OBJECT
public:
- explicit QWinRTBluetoothDeviceDiscoveryWorker();
+ QWinRTBluetoothDeviceDiscoveryWorker(QBluetoothDeviceDiscoveryAgent::DiscoveryMethods methods,
+ int interval);
~QWinRTBluetoothDeviceDiscoveryWorker();
- void start(QBluetoothDeviceDiscoveryAgent::DiscoveryMethods methods);
+ void start();
void stop();
private:
@@ -243,6 +244,8 @@ private:
int watcherId);
void generateError(QBluetoothDeviceDiscoveryAgent::Error error, const char *msg = nullptr);
void invokeDeviceFoundWithDebug(const QBluetoothDeviceInfo &info);
+ void finishDiscovery();
+ bool isFinished() const;
// Bluetooth Classic handlers
void getClassicDeviceFromId(const winrt::hstring &id);
@@ -263,9 +266,6 @@ private:
Q_INVOKABLE void incrementPendingDevicesCount();
Q_INVOKABLE void decrementPendingDevicesCountAndCheckFinished();
-public slots:
- void finishDiscovery();
-
Q_SIGNALS:
void deviceFound(const QBluetoothDeviceInfo &info);
void deviceDataChanged(const QBluetoothAddress &address, QBluetoothDeviceInfo::Fields,
@@ -282,6 +282,8 @@ private slots:
const ServiceData &serviceData,
const QList<QBluetoothUuid> &uuids);
+ void stopAdvertisementWatcher();
+
private:
struct LEAdvertisingInfo {
QList<QBluetoothUuid> services;
@@ -303,6 +305,7 @@ private:
std::shared_ptr<AdvertisementWatcherWrapper> m_advertisementWatcher;
bool m_classicScanStarted = false;
bool m_lowEnergyScanStarted = false;
+ QTimer *m_leScanTimer = nullptr;
};
static void invokeIncrementPendingDevicesCount(QObject *context)
@@ -316,7 +319,9 @@ static void invokeDecrementPendingDevicesCountAndCheckFinished(QObject *context)
Qt::QueuedConnection);
}
-QWinRTBluetoothDeviceDiscoveryWorker::QWinRTBluetoothDeviceDiscoveryWorker()
+QWinRTBluetoothDeviceDiscoveryWorker::QWinRTBluetoothDeviceDiscoveryWorker(
+ QBluetoothDeviceDiscoveryAgent::DiscoveryMethods methods, int interval)
+ : requestedModes(methods)
{
qRegisterMetaType<QBluetoothDeviceInfo>();
qRegisterMetaType<QBluetoothDeviceInfo::Fields>();
@@ -328,6 +333,18 @@ QWinRTBluetoothDeviceDiscoveryWorker::QWinRTBluetoothDeviceDiscoveryWorker()
const auto leSelector = BluetoothLEDevice::GetDeviceSelectorFromPairingState(true);
m_lowEnergyWatcher = createDeviceWatcher(leSelector, LowEnergyWatcherId);
m_advertisementWatcher = createAdvertisementWatcher();
+
+ // Docs claim that a negative interval means that the backend handles it on its own
+ if (interval < 0)
+ interval = 40000;
+
+ if (interval != 0) {
+ m_leScanTimer = new QTimer(this);
+ m_leScanTimer->setSingleShot(true);
+ m_leScanTimer->setInterval(interval);
+ connect(m_leScanTimer, &QTimer::timeout, this,
+ &QWinRTBluetoothDeviceDiscoveryWorker::stopAdvertisementWatcher);
+ }
}
QWinRTBluetoothDeviceDiscoveryWorker::~QWinRTBluetoothDeviceDiscoveryWorker()
@@ -335,10 +352,8 @@ QWinRTBluetoothDeviceDiscoveryWorker::~QWinRTBluetoothDeviceDiscoveryWorker()
stop();
}
-void QWinRTBluetoothDeviceDiscoveryWorker::start(QBluetoothDeviceDiscoveryAgent::DiscoveryMethods methods)
+void QWinRTBluetoothDeviceDiscoveryWorker::start()
{
- requestedModes = methods;
-
if (requestedModes & QBluetoothDeviceDiscoveryAgent::ClassicMethod) {
if (m_classicWatcher && m_classicWatcher->init()) {
m_classicWatcher->start();
@@ -359,6 +374,8 @@ void QWinRTBluetoothDeviceDiscoveryWorker::start(QBluetoothDeviceDiscoveryAgent:
if (m_advertisementWatcher) {
m_advertisementWatcher->init();
m_advertisementWatcher->start();
+ if (m_leScanTimer)
+ m_leScanTimer->start();
} else {
generateError(QBluetoothDeviceDiscoveryAgent::Error::UnknownError,
"Could not start low energy advertisement watcher");
@@ -381,6 +398,14 @@ void QWinRTBluetoothDeviceDiscoveryWorker::finishDiscovery()
emit scanFinished();
}
+bool QWinRTBluetoothDeviceDiscoveryWorker::isFinished() const
+{
+ // If the interval is set to 0, we do not start a timer, and that means
+ // that we need to wait for the user to explicitly call stop()
+ return (m_pendingDevices == 0) && !m_lowEnergyScanStarted && !m_classicScanStarted
+ && (m_leScanTimer && !m_leScanTimer->isActive());
+}
+
void QWinRTBluetoothDeviceDiscoveryWorker::onBluetoothDeviceFound(winrt::hstring deviceId, int watcherId)
{
if (watcherId == ClassicWatcherId)
@@ -400,11 +425,8 @@ void QWinRTBluetoothDeviceDiscoveryWorker::onDeviceEnumerationCompleted(int watc
m_lowEnergyWatcher->stop();
m_lowEnergyScanStarted = false;
}
- // TODO - probably reconsider this condition later
- if (!m_lowEnergyScanStarted && !m_classicScanStarted && !m_pendingDevices
- && !(requestedModes & QBluetoothDeviceDiscoveryAgent::LowEnergyMethod)) {
+ if (isFinished())
finishDiscovery();
- }
}
// this function executes in main worker thread
@@ -480,6 +502,13 @@ void QWinRTBluetoothDeviceDiscoveryWorker::onAdvertisementDataReceived(
});
}
+void QWinRTBluetoothDeviceDiscoveryWorker::stopAdvertisementWatcher()
+{
+ m_advertisementWatcher->stop();
+ if (isFinished())
+ finishDiscovery();
+}
+
std::shared_ptr<QBluetoothDeviceWatcherWinRT>
QWinRTBluetoothDeviceDiscoveryWorker::createDeviceWatcher(winrt::hstring selector, int watcherId)
{
@@ -608,10 +637,9 @@ void QWinRTBluetoothDeviceDiscoveryWorker::incrementPendingDevicesCount()
void QWinRTBluetoothDeviceDiscoveryWorker::decrementPendingDevicesCountAndCheckFinished()
{
- if ((--m_pendingDevices == 0) && !m_classicScanStarted && !m_lowEnergyScanStarted
- && !(requestedModes & QBluetoothDeviceDiscoveryAgent::LowEnergyMethod)) {
+ --m_pendingDevices;
+ if (isFinished())
finishDiscovery();
- }
}
// this function executes in main worker thread
@@ -764,7 +792,8 @@ void QBluetoothDeviceDiscoveryAgentPrivate::start(QBluetoothDeviceDiscoveryAgent
if (worker)
return;
- worker = std::make_shared<QWinRTBluetoothDeviceDiscoveryWorker>();
+ worker = std::make_shared<QWinRTBluetoothDeviceDiscoveryWorker>(methods,
+ lowEnergySearchTimeout);
discoveredDevices.clear();
connect(worker.get(), &QWinRTBluetoothDeviceDiscoveryWorker::deviceFound,
this, &QBluetoothDeviceDiscoveryAgentPrivate::registerDevice);
@@ -774,18 +803,7 @@ void QBluetoothDeviceDiscoveryAgentPrivate::start(QBluetoothDeviceDiscoveryAgent
this, &QBluetoothDeviceDiscoveryAgentPrivate::onErrorOccured);
connect(worker.get(), &QWinRTBluetoothDeviceDiscoveryWorker::scanFinished,
this, &QBluetoothDeviceDiscoveryAgentPrivate::onScanFinished);
- worker->start(methods);
-
- if (lowEnergySearchTimeout > 0 && methods & QBluetoothDeviceDiscoveryAgent::LowEnergyMethod) { // otherwise no timeout and stop() required
- if (!leScanTimer) {
- leScanTimer = new QTimer(this);
- leScanTimer->setSingleShot(true);
- }
- connect(leScanTimer, &QTimer::timeout,
- worker.get(), &QWinRTBluetoothDeviceDiscoveryWorker::finishDiscovery);
- leScanTimer->setInterval(lowEnergySearchTimeout);
- leScanTimer->start();
- }
+ worker->start();
}
void QBluetoothDeviceDiscoveryAgentPrivate::stop()
@@ -796,8 +814,6 @@ void QBluetoothDeviceDiscoveryAgentPrivate::stop()
disconnectAndClearWorker();
emit q->canceled();
}
- if (leScanTimer)
- leScanTimer->stop();
}
void QBluetoothDeviceDiscoveryAgentPrivate::registerDevice(const QBluetoothDeviceInfo &info)
@@ -879,10 +895,6 @@ void QBluetoothDeviceDiscoveryAgentPrivate::disconnectAndClearWorker()
this, &QBluetoothDeviceDiscoveryAgentPrivate::updateDeviceData);
disconnect(worker.get(), &QWinRTBluetoothDeviceDiscoveryWorker::errorOccured,
this, &QBluetoothDeviceDiscoveryAgentPrivate::onErrorOccured);
- if (leScanTimer) {
- disconnect(leScanTimer, &QTimer::timeout,
- worker.get(), &QWinRTBluetoothDeviceDiscoveryWorker::finishDiscovery);
- }
worker = nullptr;
}