summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorAlex Blasche <alexander.blasche@digia.com>2014-05-22 14:58:48 +0200
committerThe Qt Project <gerrit-noreply@qt-project.org>2014-05-27 12:59:10 +0200
commit19f10aae3d333ef6486ea1390998f0674fd4d89e (patch)
tree716c07b78e68fe76c78bd2a20deed3d8425f0f18
parentd4537ea1e887510cce1d42437b92f26b52e30d71 (diff)
Bluez4: Ensure QBluetoothLocalDevice becomes invalid if adapter disappears
The DBus object disappears when the dongle is removed. Once a QBluetoothLocalDevice instance is invalid it remains invalid. The patch further ensures that an invalid instance does not initiate pairing activitiy. Last but not least this patch fixes a memory leak in case a DBus error occurs during the adapter initialization. Task-number: QTBUG-38399 Change-Id: I2e13e393060c77fab5f79d5451dd6fe9a2a6e3bb Reviewed-by: Aaron McCarthy <mccarthy.aaron@gmail.com>
-rw-r--r--src/bluetooth/qbluetoothlocaldevice.cpp10
-rw-r--r--src/bluetooth/qbluetoothlocaldevice_bluez.cpp56
-rw-r--r--src/bluetooth/qbluetoothlocaldevice_p.h3
3 files changed, 62 insertions, 7 deletions
diff --git a/src/bluetooth/qbluetoothlocaldevice.cpp b/src/bluetooth/qbluetoothlocaldevice.cpp
index 14140846..6560e135 100644
--- a/src/bluetooth/qbluetoothlocaldevice.cpp
+++ b/src/bluetooth/qbluetoothlocaldevice.cpp
@@ -125,8 +125,16 @@ QBluetoothLocalDevice::~QBluetoothLocalDevice()
}
/*!
- Returns true if the QBluetoothLocalDevice represents an available local Bluetooth device;
+ Returns \c true if the QBluetoothLocalDevice represents an available local Bluetooth device;
otherwise return false.
+
+ If the local Bluetooth adapter represented by an instance of this class
+ is removed from the system (e.g. removal of the underlying Bluetooth dongle)
+ then this instance will become invalid. An already invalid QBluetoothLocalDevice instance
+ remains invalid even if the same Bluetooth adapter is returned to
+ the system.
+
+ \sa allDevices()
*/
bool QBluetoothLocalDevice::isValid() const
{
diff --git a/src/bluetooth/qbluetoothlocaldevice_bluez.cpp b/src/bluetooth/qbluetoothlocaldevice_bluez.cpp
index ac694f34..d2c8ac1d 100644
--- a/src/bluetooth/qbluetoothlocaldevice_bluez.cpp
+++ b/src/bluetooth/qbluetoothlocaldevice_bluez.cpp
@@ -218,7 +218,7 @@ static inline OrgBluezDeviceInterface *getDevice(const QBluetoothAddress &addres
void QBluetoothLocalDevice::requestPairing(const QBluetoothAddress &address, Pairing pairing)
{
- if (address.isNull()) {
+ if (!isValid() || address.isNull()) {
QMetaObject::invokeMethod(this, "error", Qt::QueuedConnection,
Q_ARG(QBluetoothLocalDevice::Error, QBluetoothLocalDevice::PairingError));
return;
@@ -347,7 +347,8 @@ QBluetoothLocalDevice::Pairing QBluetoothLocalDevice::pairingStatus(const QBluet
}
QBluetoothLocalDevicePrivate::QBluetoothLocalDevicePrivate(QBluetoothLocalDevice *q, QBluetoothAddress address)
- : adapter(0), agent(0), localAddress(address), pendingHostModeChange(-1), msgConnection(0), q_ptr(q)
+ : adapter(0), agent(0), manager(0),
+ localAddress(address), pendingHostModeChange(-1), msgConnection(0), q_ptr(q)
{
initializeAdapter();
connectDeviceChanges();
@@ -368,6 +369,7 @@ QBluetoothLocalDevicePrivate::~QBluetoothLocalDevicePrivate()
delete msgConnection;
delete adapter;
delete agent;
+ delete manager;
qDeleteAll(devices);
}
@@ -376,17 +378,19 @@ void QBluetoothLocalDevicePrivate::initializeAdapter()
if (adapter)
return;
- OrgBluezManagerInterface manager(QLatin1String("org.bluez"), QLatin1String("/"), QDBusConnection::systemBus());
+ QScopedPointer<OrgBluezManagerInterface> man(new OrgBluezManagerInterface(
+ QStringLiteral("org.bluez"), QStringLiteral("/"),
+ QDBusConnection::systemBus()));
if (localAddress == QBluetoothAddress()) {
- QDBusPendingReply<QDBusObjectPath> reply = manager.DefaultAdapter();
+ QDBusPendingReply<QDBusObjectPath> reply = man->DefaultAdapter();
reply.waitForFinished();
if (reply.isError())
return;
adapter = new OrgBluezAdapterInterface(QLatin1String("org.bluez"), reply.value().path(), QDBusConnection::systemBus());
} else {
- QDBusPendingReply<QList<QDBusObjectPath> > reply = manager.ListAdapters();
+ QDBusPendingReply<QList<QDBusObjectPath> > reply = man->ListAdapters();
reply.waitForFinished();
if (reply.isError())
return;
@@ -396,8 +400,10 @@ void QBluetoothLocalDevicePrivate::initializeAdapter()
QDBusPendingReply<QVariantMap> reply = tmpAdapter->GetProperties();
reply.waitForFinished();
- if (reply.isError())
+ if (reply.isError()) {
+ delete tmpAdapter;
continue;
+ }
QBluetoothAddress path_address(reply.value().value(QLatin1String("Address")).toString());
@@ -410,6 +416,11 @@ void QBluetoothLocalDevicePrivate::initializeAdapter()
}
}
+ // monitor case when local adapter is removed
+ manager = man.take();
+ connect(manager, SIGNAL(AdapterRemoved(QDBusObjectPath)),
+ this, SLOT(adapterRemoved(QDBusObjectPath)));
+
currentMode = static_cast<QBluetoothLocalDevice::HostMode>(-1);
if (adapter) {
connect(adapter, SIGNAL(PropertyChanged(QString,QDBusVariant)), SLOT(PropertyChanged(QString,QDBusVariant)));
@@ -425,6 +436,39 @@ bool QBluetoothLocalDevicePrivate::isValid() const
return adapter;
}
+// Bluez 4
+void QBluetoothLocalDevicePrivate::adapterRemoved(const QDBusObjectPath &devicePath)
+{
+ if (!adapter )
+ return;
+
+ if (adapter->path() != devicePath.path())
+ return;
+
+ qCDebug(QT_BT_BLUEZ) << "Adapter" << devicePath.path()
+ << "was removed. Invalidating object.";
+ // the current adapter was removed
+ delete adapter;
+ adapter = 0;
+ manager->deleteLater();
+ manager = 0;
+
+ // stop all pairing related activities
+ if (agent) {
+ QDBusConnection::systemBus().unregisterObject(agent_path);
+ delete agent;
+ agent = 0;
+ }
+
+ delete msgConnection;
+ msgConnection = 0;
+
+ // stop all connectivity monitoring
+ qDeleteAll(devices);
+ devices.clear();
+ connectedDevicesSet.clear();
+}
+
void QBluetoothLocalDevicePrivate::RequestConfirmation(const QDBusObjectPath &in0, uint in1)
{
Q_UNUSED(in0);
diff --git a/src/bluetooth/qbluetoothlocaldevice_p.h b/src/bluetooth/qbluetoothlocaldevice_p.h
index f00c33bf..66eb366c 100644
--- a/src/bluetooth/qbluetoothlocaldevice_p.h
+++ b/src/bluetooth/qbluetoothlocaldevice_p.h
@@ -56,6 +56,7 @@
class OrgBluezAdapterInterface;
class OrgBluezAgentAdaptor;
class OrgBluezDeviceInterface;
+class OrgBluezManagerInterface;
QT_BEGIN_NAMESPACE
class QDBusPendingCallWatcher;
@@ -130,6 +131,7 @@ public:
QSet<QBluetoothAddress> connectedDevicesSet;
OrgBluezAdapterInterface *adapter;
OrgBluezAgentAdaptor *agent;
+ OrgBluezManagerInterface *manager;
QList<QBluetoothAddress> connectedDevices() const;
@@ -158,6 +160,7 @@ public Q_SLOTS: // METHODS
void _q_deviceRemoved(const QDBusObjectPath &device);
void _q_devicePropertyChanged(const QString &property, const QDBusVariant &value);
bool isValid() const;
+ void adapterRemoved(const QDBusObjectPath &device);
private:
void createCache();