Merge remote-tracking branch 'gerrit/5.4.1' into 5.4

Change-Id: I1d15de1e31aeecfe162d700c632ad59cc0d6077d
This commit is contained in:
Alex Blasche 2015-02-10 11:20:35 +01:00
commit b398e069ca
9 changed files with 112 additions and 60 deletions

38
dist/changes-5.4.1 vendored Normal file
View File

@ -0,0 +1,38 @@
Qt 5.4.1 is a bug-fix release. It maintains both forward and backward
compatibility (source and binary) with Qt 5.4.0.
For more details, refer to the online documentation included in this
distribution. The documentation is also available online:
http://doc.qt.io/qt-5.4
The Qt version 5.4 series is binary compatible with the 5.3.x series.
Applications compiled for 5.3 will continue to run with 5.4.
Some of the changes listed in this file include issue tracking numbers
corresponding to tasks in the Qt Bug Tracker:
http://bugreports.qt.io/
Each of these identifiers can be entered in the bug tracker to obtain more
information about a particular change.
****************************************************************************
* Library *
****************************************************************************
QtBluetooth
-----------
- General:
* Extended documentation with regards to Bluetooth Low Energy. The
affected classes were QLowEnergyController and QLowEnergyService.
* LowEnergyScanner and chat examples improved.
- QBluetoothServer:
* [QTBUG-43806] Fixed SDP registration of PublicBrowseGroup in BlueZ 5.x.
- QLowEnergyController:
* Fixed blocking of ATT command processing due to a reconnect to the target
device.

View File

@ -101,8 +101,10 @@ void ChatServer::startServer(const QBluetoothAddress& localAdapter)
//! [Service UUID set]
//! [Service Discoverability]
QBluetoothServiceInfo::Sequence publicBrowse;
publicBrowse << QVariant::fromValue(QBluetoothUuid(QBluetoothUuid::PublicBrowseGroup));
serviceInfo.setAttribute(QBluetoothServiceInfo::BrowseGroupList,
QBluetoothUuid(QBluetoothUuid::PublicBrowseGroup));
publicBrowse);
//! [Service Discoverability]
//! [Protocol descriptor list]

View File

@ -41,9 +41,11 @@
#include "chat.h"
#include <QApplication>
//#include <QtCore/QLoggingCategory>
int main(int argc, char *argv[])
{
//QLoggingCategory::setFilterRules(QStringLiteral("qt.bluetooth* = true"));
QApplication app(argc, argv);
Chat d;

View File

@ -136,6 +136,8 @@ void RemoteSelector::on_remoteDevices_itemActivated(QListWidgetItem *item)
{
qDebug() << "got click" << item->text();
m_service = m_discoveredServices.value(item);
if (m_discoveryAgent->isActive())
m_discoveryAgent->stop();
accept();
}

View File

@ -204,8 +204,10 @@ QBluetoothServiceInfo QBluetoothServer::listen(const QBluetoothUuid &uuid, const
//! [listen]
QBluetoothServiceInfo serviceInfo;
serviceInfo.setAttribute(QBluetoothServiceInfo::ServiceName, serviceName);
QBluetoothServiceInfo::Sequence browseSequence;
browseSequence << QVariant::fromValue(QBluetoothUuid(QBluetoothUuid::PublicBrowseGroup));
serviceInfo.setAttribute(QBluetoothServiceInfo::BrowseGroupList,
QBluetoothUuid(QBluetoothUuid::PublicBrowseGroup));
browseSequence);
QBluetoothServiceInfo::Sequence classId;
classId << QVariant::fromValue(QBluetoothUuid(QBluetoothUuid::SerialPort));

View File

@ -183,6 +183,11 @@ QBluetoothServiceDiscoveryAgent::QBluetoothServiceDiscoveryAgent(const QBluetoot
QBluetoothServiceDiscoveryAgent::~QBluetoothServiceDiscoveryAgent()
{
if (isActive()) {
disconnect(); //don't emit any signals due to stop()
stop();
}
delete d_ptr;
}

View File

@ -42,6 +42,10 @@
#include <QtBluetooth/QBluetoothUuid>
#include <QtBluetooth/QBluetoothDeviceDiscoveryAgent>
#ifdef QT_BLUEZ_BLUETOOTH
#include <QtCore/qprocess.h>
#endif
QT_BEGIN_NAMESPACE
class QBluetoothAddress;
@ -106,7 +110,7 @@ private:
#ifdef QT_BLUEZ_BLUETOOTH
Q_PRIVATE_SLOT(d_func(), void _q_discoveredServices(QDBusPendingCallWatcher*))
Q_PRIVATE_SLOT(d_func(), void _q_createdDevice(QDBusPendingCallWatcher*))
Q_PRIVATE_SLOT(d_func(), void _q_finishSdpScan(QBluetoothServiceDiscoveryAgent::Error, const QString &, const QStringList &))
Q_PRIVATE_SLOT(d_func(), void _q_sdpScannerDone(int,QProcess::ExitStatus))
#endif
#ifdef QT_ANDROID_BLUETOOTH
Q_PRIVATE_SLOT(d_func(), void _q_processFetchedUuids(const QBluetoothAddress &address,

View File

@ -65,7 +65,7 @@ static inline void convertAddress(quint64 from, quint8 (&to)[6])
QBluetoothServiceDiscoveryAgentPrivate::QBluetoothServiceDiscoveryAgentPrivate(const QBluetoothAddress &deviceAdapter)
: error(QBluetoothServiceDiscoveryAgent::NoError), m_deviceAdapterAddress(deviceAdapter), state(Inactive), deviceDiscoveryAgent(0),
mode(QBluetoothServiceDiscoveryAgent::MinimalDiscovery), singleDevice(false),
manager(0), managerBluez5(0), adapter(0), device(0)
manager(0), managerBluez5(0), adapter(0), device(0), sdpScannerProcess(0)
{
if (isBluez5()) {
managerBluez5 = new OrgFreedesktopDBusObjectManagerInterface(
@ -136,6 +136,7 @@ void QBluetoothServiceDiscoveryAgentPrivate::start(const QBluetoothAddress &addr
}
// Bluez 5
void QBluetoothServiceDiscoveryAgentPrivate::startBluez5(const QBluetoothAddress &address)
{
Q_Q(QBluetoothServiceDiscoveryAgent);
@ -185,81 +186,64 @@ void QBluetoothServiceDiscoveryAgentPrivate::startBluez5(const QBluetoothAddress
if (DiscoveryMode() == QBluetoothServiceDiscoveryAgent::MinimalDiscovery) {
performMinimalServiceDiscovery(address);
} else {
// we need to run the discovery in a different thread
// as it involves blocking calls
QtConcurrent::run(this, &QBluetoothServiceDiscoveryAgentPrivate::runSdpScan,
address, QBluetoothAddress(adapter.address()));
runExternalSdpScan(address, QBluetoothAddress(adapter.address()));
}
}
/*
* This function runs in a different thread. We need to be very careful what we
* access from here. That's why invokeMethod is used below.
*
/* Bluez 5
* src/tools/sdpscanner performs an SDP scan. This is
* done out-of-process to avoid license issues. At this stage Bluez uses GPLv2.
*/
void QBluetoothServiceDiscoveryAgentPrivate::runSdpScan(
void QBluetoothServiceDiscoveryAgentPrivate::runExternalSdpScan(
const QBluetoothAddress &remoteAddress, const QBluetoothAddress localAddress)
{
Q_Q(QBluetoothServiceDiscoveryAgent);
const QString binPath = QLibraryInfo::location(QLibraryInfo::BinariesPath);
if (!sdpScannerProcess) {
const QString binPath = QLibraryInfo::location(QLibraryInfo::BinariesPath);
QFileInfo fileInfo(binPath, QStringLiteral("sdpscanner"));
if (!fileInfo.exists() || !fileInfo.isExecutable()) {
_q_finishSdpScan(QBluetoothServiceDiscoveryAgent::InputOutputError,
QBluetoothServiceDiscoveryAgent::tr("Unable to find sdpscanner"),
QStringList());
qCWarning(QT_BT_BLUEZ) << "Cannot find sdpscanner:"
<< fileInfo.canonicalFilePath();
return;
}
sdpScannerProcess = new QProcess(q);
sdpScannerProcess->setReadChannel(QProcess::StandardOutput);
sdpScannerProcess->setProgram(fileInfo.canonicalFilePath());
q->connect(sdpScannerProcess, SIGNAL(finished(int,QProcess::ExitStatus)),
q, SLOT(_q_sdpScannerDone(int,QProcess::ExitStatus)));
QFileInfo fileInfo(binPath, QStringLiteral("sdpscanner"));
if (!fileInfo.exists() || !fileInfo.isExecutable()) {
QMetaObject::invokeMethod(q, "_q_finishSdpScan", Qt::QueuedConnection,
Q_ARG(QBluetoothServiceDiscoveryAgent::Error,
QBluetoothServiceDiscoveryAgent::InputOutputError),
Q_ARG(QString,
QBluetoothServiceDiscoveryAgent::tr("Unable to find sdpscanner")),
Q_ARG(QStringList, QStringList()));
qCWarning(QT_BT_BLUEZ) << "Cannot find sdpscanner:"
<< fileInfo.canonicalFilePath();
return;
}
QStringList arguments;
arguments << remoteAddress.toString() << localAddress.toString();
QByteArray output;
sdpScannerProcess->setArguments(arguments);
sdpScannerProcess->start();
}
QProcess process;
process.setProcessChannelMode(QProcess::ForwardedErrorChannel);
process.setReadChannel(QProcess::StandardOutput);
process.start(fileInfo.canonicalFilePath(), arguments);
if (process.waitForStarted(-1)) {
while (process.waitForReadyRead(-1))
output += process.readAllStandardOutput();
}
process.waitForFinished();
if (process.exitStatus() != QProcess::NormalExit
|| process.exitCode() != 0) {
qCWarning(QT_BT_BLUEZ) << "SDP scan failure"
<< process.exitStatus() << process.exitCode()
<< remoteAddress;
// Bluez 5
void QBluetoothServiceDiscoveryAgentPrivate::_q_sdpScannerDone(int exitCode, QProcess::ExitStatus status)
{
if (status != QProcess::NormalExit || exitCode != 0) {
qCWarning(QT_BT_BLUEZ) << "SDP scan failure" << status << exitCode;
if (singleDevice) {
QMetaObject::invokeMethod(q, "_q_finishSdpScan", Qt::QueuedConnection,
Q_ARG(QBluetoothServiceDiscoveryAgent::Error,
QBluetoothServiceDiscoveryAgent::InputOutputError),
Q_ARG(QString,
QBluetoothServiceDiscoveryAgent::tr("Unable to perform SDP scan")),
Q_ARG(QStringList, QStringList()));
_q_finishSdpScan(QBluetoothServiceDiscoveryAgent::InputOutputError,
QBluetoothServiceDiscoveryAgent::tr("Unable to perform SDP scan"),
QStringList());
} else {
// go to next device
QMetaObject::invokeMethod(q, "_q_finishSdpScan", Qt::QueuedConnection,
Q_ARG(QBluetoothServiceDiscoveryAgent::Error,
QBluetoothServiceDiscoveryAgent::NoError),
Q_ARG(QString, QString()),
Q_ARG(QStringList, QStringList()));
_q_finishSdpScan(QBluetoothServiceDiscoveryAgent::NoError, QString(), QStringList());
}
return;
}
QStringList xmlRecords;
const QByteArray output = sdpScannerProcess->readAllStandardOutput();
const QString decodedData = QString::fromUtf8(QByteArray::fromBase64(output));
// split the various xml docs up
@ -276,13 +260,10 @@ void QBluetoothServiceDiscoveryAgentPrivate::runSdpScan(
} while ( start != -1);
}
QMetaObject::invokeMethod(q, "_q_finishSdpScan", Qt::QueuedConnection,
Q_ARG(QBluetoothServiceDiscoveryAgent::Error,
QBluetoothServiceDiscoveryAgent::NoError),
Q_ARG(QString, QString()),
Q_ARG(QStringList, xmlRecords));
_q_finishSdpScan(QBluetoothServiceDiscoveryAgent::NoError, QString(), xmlRecords);
}
// Bluez 5
void QBluetoothServiceDiscoveryAgentPrivate::_q_finishSdpScan(QBluetoothServiceDiscoveryAgent::Error errorCode,
const QString &errorDescription,
const QStringList &xmlRecords)
@ -352,8 +333,19 @@ void QBluetoothServiceDiscoveryAgentPrivate::stop()
Q_ASSERT(!device);
}
discoveredDevices.clear();
setDiscoveryState(Inactive);
// must happen after discoveredDevices.clear() above to avoid retrigger of next scan
// while waitForFinished() is waiting
if (sdpScannerProcess) { // Bluez 5
if (sdpScannerProcess->state() != QProcess::NotRunning) {
sdpScannerProcess->kill();
sdpScannerProcess->waitForFinished();
}
}
Q_Q(QBluetoothServiceDiscoveryAgent);
emit q->canceled();
}
@ -591,6 +583,7 @@ QBluetoothServiceInfo QBluetoothServiceDiscoveryAgentPrivate::parseServiceXml(
return serviceInfo;
}
// Bluez 5
void QBluetoothServiceDiscoveryAgentPrivate::performMinimalServiceDiscovery(const QBluetoothAddress &deviceAddress)
{
if (foundHostAdapterPath.isEmpty()) {

View File

@ -58,6 +58,7 @@ class OrgBluezManagerInterface;
class OrgBluezAdapterInterface;
class OrgBluezDeviceInterface;
class OrgFreedesktopDBusObjectManagerInterface;
#include <QtCore/qprocess.h>
QT_BEGIN_NAMESPACE
class QDBusPendingCallWatcher;
@ -127,6 +128,7 @@ public:
void _q_discoverGattCharacteristics(QDBusPendingCallWatcher *watcher);
void _q_discoveredGattCharacteristic(QDBusPendingCallWatcher *watcher);
*/
void _q_sdpScannerDone(int exitCode, QProcess::ExitStatus status);
void _q_finishSdpScan(QBluetoothServiceDiscoveryAgent::Error errorCode,
const QString &errorDescription,
const QStringList &xmlRecords);
@ -147,8 +149,9 @@ private:
#ifdef QT_BLUEZ_BLUETOOTH
void startBluez5(const QBluetoothAddress &address);
void runSdpScan(const QBluetoothAddress &remoteAddress,
void runExternalSdpScan(const QBluetoothAddress &remoteAddress,
const QBluetoothAddress localAddress);
void sdpScannerDone(int exitCode, QProcess::ExitStatus exitStatus);
QVariant readAttributeValue(QXmlStreamReader &xml);
QBluetoothServiceInfo parseServiceXml(const QString& xml);
void performMinimalServiceDiscovery(const QBluetoothAddress &deviceAddress);
@ -195,6 +198,7 @@ private:
OrgFreedesktopDBusObjectManagerInterface *managerBluez5;
OrgBluezAdapterInterface *adapter;
OrgBluezDeviceInterface *device;
QProcess *sdpScannerProcess;
#endif
#ifdef QT_ANDROID_BLUETOOTH