diff options
author | Alex Blasche <alexander.blasche@digia.com> | 2014-08-11 15:42:03 +0200 |
---|---|---|
committer | Alex Blasche <alexander.blasche@digia.com> | 2014-08-13 13:47:53 +0200 |
commit | d5422ad7c9806e6a105ae9918fae650e38aad601 (patch) | |
tree | 4c4a4ea77846a33e312a0369416febc785ee27bf | |
parent | 02a9784b2b502ade67710632c2872bda097770e3 (diff) |
Improve consistency of device discovery.
Device discovery of BTLE devices fails once the second device discovery
is performed in the current process. The first discovery always succeeds.
BTLE devices are advertised right after the start of the device discovery
session. However the discovery session never seems to stop once it is
done for the first time. This can be seen by the fact that the
Discovering property of the adapter constantly toggles between true
and false. As a consequence the second device discovery won't find
a BTLE device in 99% of all cases. The odds that the API user initiates
the second discovery right between two continues adapter searches
is rather slim.
The fix is to extend the device discovery process beyond
a toggle of a single device discovery cycle. We ignore the
end signal of the first cycle and continue to the end of the second
cycle. At the same time we rely on the perceived bug which restarts
the second cycle automatically. Just for the case that the second cycle
doesn't start automatically we utilize a timer to manually force
an end of the device discovery.
The problem is likely to be a bug in Bluez4. A negative side effect
of this workaround is a longer device discovery process.
Change-Id: I986c8d6498b2cc9ed51f4457267c53813132cf8e
Reviewed-by: Fabian Bumberger <fbumberger@rim.com>
-rw-r--r-- | src/bluetooth/qbluetoothdevicediscoveryagent.h | 1 | ||||
-rw-r--r-- | src/bluetooth/qbluetoothdevicediscoveryagent_bluez.cpp | 85 | ||||
-rw-r--r-- | src/bluetooth/qbluetoothdevicediscoveryagent_p.h | 5 |
3 files changed, 78 insertions, 13 deletions
diff --git a/src/bluetooth/qbluetoothdevicediscoveryagent.h b/src/bluetooth/qbluetoothdevicediscoveryagent.h index 89158c53..ba675d90 100644 --- a/src/bluetooth/qbluetoothdevicediscoveryagent.h +++ b/src/bluetooth/qbluetoothdevicediscoveryagent.h @@ -111,6 +111,7 @@ private: Q_PRIVATE_SLOT(d_func(), void _q_discoveryFinished()) Q_PRIVATE_SLOT(d_func(), void _q_discoveryInterrupted(const QString &path)) Q_PRIVATE_SLOT(d_func(), void _q_PropertiesChanged(const QString &interface, const QVariantMap &changed_properties, const QStringList &invalidated_properties)) + Q_PRIVATE_SLOT(d_func(), void _q_extendedDeviceDiscoveryTimeout()) #endif }; diff --git a/src/bluetooth/qbluetoothdevicediscoveryagent_bluez.cpp b/src/bluetooth/qbluetoothdevicediscoveryagent_bluez.cpp index 5d1920a6..c7fdde05 100644 --- a/src/bluetooth/qbluetoothdevicediscoveryagent_bluez.cpp +++ b/src/bluetooth/qbluetoothdevicediscoveryagent_bluez.cpp @@ -69,10 +69,11 @@ QBluetoothDeviceDiscoveryAgentPrivate::QBluetoothDeviceDiscoveryAgentPrivate( managerBluez5(0), adapterBluez5(0), discoveryTimer(0), + useExtendedDiscovery(false), q_ptr(parent) { + Q_Q(QBluetoothDeviceDiscoveryAgent); if (isBluez5()) { - Q_Q(QBluetoothDeviceDiscoveryAgent); managerBluez5 = new OrgFreedesktopDBusObjectManagerInterface( QStringLiteral("org.bluez"), QStringLiteral("/"), @@ -84,6 +85,11 @@ QBluetoothDeviceDiscoveryAgentPrivate::QBluetoothDeviceDiscoveryAgentPrivate( } else { manager = new OrgBluezManagerInterface(QStringLiteral("org.bluez"), QStringLiteral("/"), QDBusConnection::systemBus(), parent); + QObject::connect(&extendedDiscoveryTimer, + SIGNAL(timeout()), + q, SLOT(_q_extendedDeviceDiscoveryTimeout())); + extendedDiscoveryTimer.setInterval(10000); + extendedDiscoveryTimer.setSingleShot(true); } inquiryType = QBluetoothDeviceDiscoveryAgent::GeneralUnlimitedInquiry; } @@ -169,6 +175,26 @@ void QBluetoothDeviceDiscoveryAgentPrivate::start() return; } + if (propertiesReply.value().value(QStringLiteral("Discovering")).toBool()) { + /* The discovery session is already ongoing. BTLE devices are advertised + immediately after the start of the device discovery session. Hence if the + session is already ongoing, we have just missed the BTLE device + advertisement. + + This always happens during the second device discovery run in + the current process. The first discovery doesn't have this issue. + As to why the discovery session remains active despite the previous one + being terminated is not known. This may be a bug in Bluez4. + + To workaround this issue we have to wait for two discovery + sessions cycles. + */ + qCDebug(QT_BT_BLUEZ) << "Using BTLE device discovery workaround."; + useExtendedDiscovery = true; + } else { + useExtendedDiscovery = false; + } + QDBusPendingReply<> discoveryReply = adapter->StartDiscovery(); if (discoveryReply.isError()) { delete adapter; @@ -382,23 +408,56 @@ void QBluetoothDeviceDiscoveryAgentPrivate::_q_propertyChanged(const QString &na { qCDebug(QT_BT_BLUEZ) << Q_FUNC_INFO << name << value.variant(); - if (name == QLatin1String("Discovering") && !value.variant().toBool()) { - Q_Q(QBluetoothDeviceDiscoveryAgent); - adapter->deleteLater(); - adapter = 0; - if (pendingCancel && !pendingStart) { - emit q->canceled(); - pendingCancel = false; - } else if (pendingStart) { - pendingStart = false; - pendingCancel = false; - start(); + if (name == QLatin1String("Discovering")) { + if (!value.variant().toBool()) { + Q_Q(QBluetoothDeviceDiscoveryAgent); + if (pendingCancel && !pendingStart) { + adapter->deleteLater(); + adapter = 0; + + emit q->canceled(); + pendingCancel = false; + } else if (pendingStart) { + adapter->deleteLater(); + adapter = 0; + + pendingStart = false; + pendingCancel = false; + start(); + } else { + if (useExtendedDiscovery) { + useExtendedDiscovery = false; + /* We don't use the Start/StopDiscovery combo here + Using this combo surppresses the BTLE device. + */ + extendedDiscoveryTimer.start(); + return; + } + + adapter->deleteLater(); + adapter = 0; + emit q->finished(); + } } else { - emit q->finished(); + if (extendedDiscoveryTimer.isActive()) + extendedDiscoveryTimer.stop(); } } } +void QBluetoothDeviceDiscoveryAgentPrivate::_q_extendedDeviceDiscoveryTimeout() +{ + + if (adapter) { + adapter->deleteLater(); + adapter = 0; + } + if (isActive()) { + Q_Q(QBluetoothDeviceDiscoveryAgent); + emit q->finished(); + } +} + void QBluetoothDeviceDiscoveryAgentPrivate::_q_InterfacesAdded(const QDBusObjectPath &object_path, InterfaceList interfaces_and_properties) { diff --git a/src/bluetooth/qbluetoothdevicediscoveryagent_p.h b/src/bluetooth/qbluetoothdevicediscoveryagent_p.h index 168b6c0c..c4e804d3 100644 --- a/src/bluetooth/qbluetoothdevicediscoveryagent_p.h +++ b/src/bluetooth/qbluetoothdevicediscoveryagent_p.h @@ -102,6 +102,7 @@ public: void _q_PropertiesChanged(const QString &interface, const QVariantMap &changed_properties, const QStringList &invalidated_properties); + void _q_extendedDeviceDiscoveryTimeout(); #endif private: @@ -136,6 +137,10 @@ private: void deviceFoundBluez5(const QString& devicePath); void startBluez5(); + + bool useExtendedDiscovery; + QTimer extendedDiscoveryTimer; + #elif defined(QT_QNX_BLUETOOTH) private slots: void finished(); |