summaryrefslogtreecommitdiffstats
path: root/src
diff options
context:
space:
mode:
authorAlex Blasche <alexander.blasche@theqtcompany.com>2015-04-01 08:33:21 +0200
committerAlex Blasche <alexander.blasche@theqtcompany.com>2015-04-01 08:36:34 +0200
commit4ed0678f93d7fc6a9d0d43dfdfe6608e827eb176 (patch)
tree3faa743c8a7a84e9f97408acd625c4ed797e6f81 /src
parentec82c463d3f83454130dccfa71988af13768c5eb (diff)
parentb4bf23453e65995bdd8827b6e146edd5cafeddc3 (diff)
Merge branch '5.4' into 5.5
Diffstat (limited to 'src')
-rw-r--r--src/bluetooth/qbluetoothlocaldevice_android.cpp38
-rw-r--r--src/bluetooth/qbluetoothservicediscoveryagent_bluez.cpp4
-rw-r--r--src/bluetooth/qbluetoothsocket.cpp14
-rw-r--r--src/bluetooth/qbluetoothsocket_android.cpp300
-rw-r--r--src/bluetooth/qbluetoothsocket_bluez.cpp14
-rw-r--r--src/bluetooth/qbluetoothsocket_p.h23
-rw-r--r--src/bluetooth/qlowenergycontroller_bluez.cpp20
7 files changed, 296 insertions, 117 deletions
diff --git a/src/bluetooth/qbluetoothlocaldevice_android.cpp b/src/bluetooth/qbluetoothlocaldevice_android.cpp
index 133b76b9..20ac3d0a 100644
--- a/src/bluetooth/qbluetoothlocaldevice_android.cpp
+++ b/src/bluetooth/qbluetoothlocaldevice_android.cpp
@@ -83,35 +83,20 @@ void QBluetoothLocalDevicePrivate::initialize(const QBluetoothAddress &address)
{
QAndroidJniEnvironment env;
- jclass btAdapterClass = env->FindClass("android/bluetooth/BluetoothAdapter");
- if (btAdapterClass == NULL) {
- qCWarning(QT_BT_ANDROID)
- << "Native registration unable to find class android/bluetooth/BluetoothAdapter";
- return;
- }
-
- jmethodID getDefaultAdapterID
- = env->GetStaticMethodID(btAdapterClass, "getDefaultAdapter",
- "()Landroid/bluetooth/BluetoothAdapter;");
- if (getDefaultAdapterID == NULL) {
- qCWarning(QT_BT_ANDROID)
- << "Native registration unable to get method ID: " \
- "getDefaultAdapter of android/bluetooth/BluetoothAdapter";
- return;
- }
-
- jobject btAdapterObject = env->CallStaticObjectMethod(btAdapterClass, getDefaultAdapterID);
- if (btAdapterObject == NULL) {
+ QAndroidJniObject adapter = QAndroidJniObject::callStaticObjectMethod(
+ "android/bluetooth/BluetoothAdapter", "getDefaultAdapter",
+ "()Landroid/bluetooth/BluetoothAdapter;");
+ if (!adapter.isValid()) {
+ if (env->ExceptionCheck()) {
+ env->ExceptionDescribe();
+ env->ExceptionClear();
+ }
qCWarning(QT_BT_ANDROID) << "Device does not support Bluetooth";
- env->DeleteLocalRef(btAdapterClass);
return;
}
- obj = new QAndroidJniObject(btAdapterObject);
- if (!obj->isValid()) {
- delete obj;
- obj = 0;
- } else if (!address.isNull()) {
+ obj = new QAndroidJniObject(adapter);
+ if (!address.isNull()) {
const QString localAddress
= obj->callObjectMethod("getAddress", "()Ljava/lang/String;").toString();
if (localAddress != address.toString()) {
@@ -120,9 +105,6 @@ void QBluetoothLocalDevicePrivate::initialize(const QBluetoothAddress &address)
obj = 0;
}
}
-
- env->DeleteLocalRef(btAdapterObject);
- env->DeleteLocalRef(btAdapterClass);
}
bool QBluetoothLocalDevicePrivate::isValid() const
diff --git a/src/bluetooth/qbluetoothservicediscoveryagent_bluez.cpp b/src/bluetooth/qbluetoothservicediscoveryagent_bluez.cpp
index 86d35428..f66603a9 100644
--- a/src/bluetooth/qbluetoothservicediscoveryagent_bluez.cpp
+++ b/src/bluetooth/qbluetoothservicediscoveryagent_bluez.cpp
@@ -272,7 +272,9 @@ void QBluetoothServiceDiscoveryAgentPrivate::_q_finishSdpScan(QBluetoothServiceD
if (errorCode != QBluetoothServiceDiscoveryAgent::NoError) {
qCWarning(QT_BT_BLUEZ) << "SDP search failed for"
- << discoveredDevices.at(0).address().toString();
+ << (!discoveredDevices.isEmpty()
+ ? discoveredDevices.at(0).address().toString()
+ : QStringLiteral("<Unknown>"));
// We have an error which we need to indicate and stop further processing
discoveredDevices.clear();
error = errorCode;
diff --git a/src/bluetooth/qbluetoothsocket.cpp b/src/bluetooth/qbluetoothsocket.cpp
index e82e866a..56428544 100644
--- a/src/bluetooth/qbluetoothsocket.cpp
+++ b/src/bluetooth/qbluetoothsocket.cpp
@@ -602,6 +602,13 @@ void QBluetoothSocket::abort()
Q_D(QBluetoothSocket);
setOpenMode(QIODevice::NotOpen);
+
+ if (state() == ServiceLookupState && d->discoveryAgent) {
+ d->discoveryAgent->disconnect();
+ d->discoveryAgent->stop();
+ d->discoveryAgent = 0;
+ }
+
setSocketState(ClosingState);
d->abort();
@@ -679,6 +686,13 @@ void QBluetoothSocket::close()
Q_D(QBluetoothSocket);
setOpenMode(QIODevice::NotOpen);
+
+ if (state() == ServiceLookupState && d->discoveryAgent) {
+ d->discoveryAgent->disconnect();
+ d->discoveryAgent->stop();
+ d->discoveryAgent = 0;
+ }
+
setSocketState(ClosingState);
d->close();
diff --git a/src/bluetooth/qbluetoothsocket_android.cpp b/src/bluetooth/qbluetoothsocket_android.cpp
index ab257cf4..990ab378 100644
--- a/src/bluetooth/qbluetoothsocket_android.cpp
+++ b/src/bluetooth/qbluetoothsocket_android.cpp
@@ -36,15 +36,136 @@
#include "qbluetoothsocket_p.h"
#include "qbluetoothaddress.h"
#include <QtCore/QLoggingCategory>
+#include <QtCore/QThread>
#include <QtCore/QTime>
#include <QtCore/private/qjni_p.h>
-#include <QtConcurrent/QtConcurrentRun>
#include <QtAndroidExtras/QAndroidJniEnvironment>
QT_BEGIN_NAMESPACE
Q_DECLARE_LOGGING_CATEGORY(QT_BT_ANDROID)
+#define FALLBACK_CHANNEL 1
+#define USE_FALLBACK true
+
+Q_DECLARE_METATYPE(QAndroidJniObject)
+
+
+/* BluetoothSocket.connect() can block up to 10s. Therefore it must be
+ * in a separate thread. Unfortunately if BluetoothSocket.close() is
+ * called while connect() is still blocking the resulting behavior is not reliable.
+ * This may well be an Android platform bug. In any case, close() must
+ * be queued up until connect() has returned.
+ *
+ * The WorkerThread manages the connect() and close() calls. Interaction
+ * with the main thread happens via signals and slots. There is an accepted but
+ * undesirable side effect of this approach as the user may call connect()
+ * and close() and the socket would continue to successfully connect to
+ * the remote device just to immidiately close the physical connection again.
+ *
+ * WorkerThread and SocketConnectWorker are cleaned up via the threads
+ * finished() signal.
+ */
+
+class SocketConnectWorker : public QObject
+{
+ Q_OBJECT
+public:
+ SocketConnectWorker(const QAndroidJniObject& socket,
+ const QAndroidJniObject& targetUuid)
+ : QObject(),
+ mSocketObject(socket),
+ mTargetUuid(targetUuid)
+ {
+ static int t = qRegisterMetaType<QAndroidJniObject>();
+ Q_UNUSED(t);
+ }
+
+signals:
+ void socketConnectDone(const QAndroidJniObject &socket);
+ void socketConnectFailed(const QAndroidJniObject &socket,
+ const QAndroidJniObject &targetUuid);
+public slots:
+ void connectSocket()
+ {
+ QAndroidJniEnvironment env;
+
+ qCDebug(QT_BT_ANDROID) << "Connecting socket";
+ mSocketObject.callMethod<void>("connect");
+ if (env->ExceptionCheck()) {
+ env->ExceptionDescribe();
+ env->ExceptionClear();
+
+ emit socketConnectFailed(mSocketObject, mTargetUuid);
+ QThread::currentThread()->quit();
+ return;
+ }
+
+ qCDebug(QT_BT_ANDROID) << "Socket connection established";
+ emit socketConnectDone(mSocketObject);
+ }
+
+ void closeSocket()
+ {
+ qCDebug(QT_BT_ANDROID) << "Executing queued closeSocket()";
+
+ QAndroidJniEnvironment env;
+ mSocketObject.callMethod<void>("close");
+ if (env->ExceptionCheck()) {
+
+ qCWarning(QT_BT_ANDROID) << "Error during closure of abandoned socket";
+ env->ExceptionDescribe();
+ env->ExceptionClear();
+ }
+
+ QThread::currentThread()->quit();
+ }
+
+private:
+ QAndroidJniObject mSocketObject;
+ QAndroidJniObject mTargetUuid;
+};
+
+class WorkerThread: public QThread
+{
+ Q_OBJECT
+public:
+ WorkerThread()
+ : QThread(), workerPointer(0)
+ {
+ }
+
+ // Runs in same thread as QBluetoothSocketPrivate
+ void setupWorker(QBluetoothSocketPrivate* d_ptr, const QAndroidJniObject& socketObject,
+ const QAndroidJniObject& uuidObject, bool useFallback)
+ {
+ SocketConnectWorker* worker = new SocketConnectWorker(
+ socketObject, uuidObject);
+ worker->moveToThread(this);
+
+ connect(this, &QThread::finished, worker, &QObject::deleteLater);
+ connect(this, &QThread::finished, this, &QObject::deleteLater);
+ connect(d_ptr, &QBluetoothSocketPrivate::connectJavaSocket,
+ worker, &SocketConnectWorker::connectSocket);
+ connect(d_ptr, &QBluetoothSocketPrivate::closeJavaSocket,
+ worker, &SocketConnectWorker::closeSocket);
+ connect(worker, &SocketConnectWorker::socketConnectDone,
+ d_ptr, &QBluetoothSocketPrivate::socketConnectSuccess);
+ if (useFallback) {
+ connect(worker, &SocketConnectWorker::socketConnectFailed,
+ d_ptr, &QBluetoothSocketPrivate::fallbackSocketConnectFailed);
+ } else {
+ connect(worker, &SocketConnectWorker::socketConnectFailed,
+ d_ptr, &QBluetoothSocketPrivate::defaultSocketConnectFailed);
+ }
+
+ workerPointer = worker;
+ }
+
+private:
+ QPointer<SocketConnectWorker> workerPointer;
+};
+
QBluetoothSocketPrivate::QBluetoothSocketPrivate()
: socket(-1),
socketType(QBluetoothServiceInfo::UnknownProtocol),
@@ -63,6 +184,8 @@ QBluetoothSocketPrivate::QBluetoothSocketPrivate()
QBluetoothSocketPrivate::~QBluetoothSocketPrivate()
{
+ if (state != QBluetoothSocket::UnconnectedState)
+ emit closeJavaSocket();
}
bool QBluetoothSocketPrivate::ensureNativeSocket(QBluetoothServiceInfo::Protocol type)
@@ -74,18 +197,6 @@ bool QBluetoothSocketPrivate::ensureNativeSocket(QBluetoothServiceInfo::Protocol
return false;
}
-void QBluetoothSocketPrivate::connectToService(const QBluetoothAddress &address,
- const QBluetoothUuid &uuid,
- QIODevice::OpenMode openMode,
- int fallbackServiceChannel)
-{
- Q_Q(QBluetoothSocket);
-
- q->setSocketState(QBluetoothSocket::ConnectingState);
- QtConcurrent::run(this, &QBluetoothSocketPrivate::connectToServiceConc,
- address, uuid, openMode, fallbackServiceChannel);
-}
-
bool QBluetoothSocketPrivate::fallBackConnect(QAndroidJniObject uuid, int channel)
{
qCWarning(QT_BT_ANDROID) << "Falling back to workaround.";
@@ -181,26 +292,42 @@ bool QBluetoothSocketPrivate::fallBackConnect(QAndroidJniObject uuid, int channe
}
socketObject = QAndroidJniObject(invokeResult);
- socketObject.callMethod<void>("connect");
- if (env->ExceptionCheck()) {
- env->ExceptionDescribe();
- env->ExceptionClear();
- qCWarning(QT_BT_ANDROID) << "Socket connect via workaround failed.";
- return false;
- }
+ WorkerThread *workerThread = new WorkerThread();
+ workerThread->setupWorker(this, socketObject, uuid, USE_FALLBACK);
+ workerThread->start();
+ emit connectJavaSocket();
- qCWarning(QT_BT_ANDROID) << "Workaround invoked.";
+ qCWarning(QT_BT_ANDROID) << "Workaround thread invoked.";
return true;
}
-void QBluetoothSocketPrivate::connectToServiceConc(const QBluetoothAddress &address,
- const QBluetoothUuid &uuid, QIODevice::OpenMode openMode, int fallbackServiceChannel)
+
+/*
+ * The call order during a connectToService() is as follows:
+ *
+ * 1. call connectToService()
+ * 2. wait for execution of SocketConnectThread::run()
+ * 3. if threaded connect succeeds call socketConnectSuccess() via signals
+ * -> done
+ * 4. if threaded connect fails call defaultSocketConnectFailed() via signals
+ * 5. call fallBackConnect()
+ * 6. if threaded connect on fallback channel succeeds call socketConnectSuccess()
+ * via signals
+ * -> done
+ * 7. if threaded connect on fallback channel fails call fallbackSocketConnectFailed()
+ * -> complete failure of entire connectToService()
+ * */
+void QBluetoothSocketPrivate::connectToService(const QBluetoothAddress &address,
+ const QBluetoothUuid &uuid,
+ QIODevice::OpenMode openMode)
{
Q_Q(QBluetoothSocket);
Q_UNUSED(openMode);
- qCDebug(QT_BT_ANDROID) << "connectToServiceConc()" << address.toString() << uuid.toString();
+ qCDebug(QT_BT_ANDROID) << "connectToService()" << address.toString() << uuid.toString();
+
+ q->setSocketState(QBluetoothSocket::ConnectingState);
if (!adapter.isValid()) {
qCWarning(QT_BT_ANDROID) << "Device does not support Bluetooth";
@@ -260,22 +387,21 @@ void QBluetoothSocketPrivate::connectToServiceConc(const QBluetoothAddress &addr
return;
}
- socketObject.callMethod<void>("connect");
- if (env->ExceptionCheck()) {
- env->ExceptionDescribe();
- env->ExceptionClear();
+ WorkerThread *workerThread = new WorkerThread();
+ workerThread->setupWorker(this, socketObject, uuidObject, !USE_FALLBACK);
+ workerThread->start();
+ emit connectJavaSocket();
+}
- bool success = fallBackConnect(uuidObject, fallbackServiceChannel);
- if (!success) {
- errorString = QBluetoothSocket::tr("Connection to service failed");
- socketObject = remoteDevice = QAndroidJniObject();
- q->setSocketError(QBluetoothSocket::ServiceNotFoundError);
- q->setSocketState(QBluetoothSocket::UnconnectedState);
+void QBluetoothSocketPrivate::socketConnectSuccess(const QAndroidJniObject &socket)
+{
+ Q_Q(QBluetoothSocket);
+ QAndroidJniEnvironment env;
- env->ExceptionClear(); //just in case
- return;
- }
- }
+ // test we didn't get a success from a previous connect
+ // which was cleaned up late
+ if (socket != socketObject)
+ return;
if (inputThread) {
inputThread->deleteLater();
@@ -289,13 +415,7 @@ void QBluetoothSocketPrivate::connectToServiceConc(const QBluetoothAddress &addr
env->ExceptionDescribe();
env->ExceptionClear();
- //close socket again
- socketObject.callMethod<void>("close");
- if (env->ExceptionCheck()) {
- env->ExceptionDescribe();
- env->ExceptionClear();
- }
-
+ emit closeJavaSocket();
socketObject = inputStream = outputStream = remoteDevice = QAndroidJniObject();
@@ -313,11 +433,7 @@ void QBluetoothSocketPrivate::connectToServiceConc(const QBluetoothAddress &addr
if (!inputThread->run()) {
//close socket again
- socketObject.callMethod<void>("close");
- if (env->ExceptionCheck()) {
- env->ExceptionDescribe();
- env->ExceptionClear();
- }
+ emit closeJavaSocket();
socketObject = inputStream = outputStream = remoteDevice = QAndroidJniObject();
@@ -337,6 +453,48 @@ void QBluetoothSocketPrivate::connectToServiceConc(const QBluetoothAddress &addr
emit q->connected();
}
+void QBluetoothSocketPrivate::defaultSocketConnectFailed(
+ const QAndroidJniObject &socket, const QAndroidJniObject &targetUuid)
+{
+ Q_Q(QBluetoothSocket);
+
+ // test we didn't get a fail from a previous connect
+ // which was cleaned up late - should be same socket
+ if (socket != socketObject)
+ return;
+
+ bool success = fallBackConnect(targetUuid, FALLBACK_CHANNEL);
+ if (!success) {
+ errorString = QBluetoothSocket::tr("Connection to service failed");
+ socketObject = remoteDevice = QAndroidJniObject();
+ q->setSocketError(QBluetoothSocket::ServiceNotFoundError);
+ q->setSocketState(QBluetoothSocket::UnconnectedState);
+
+ QAndroidJniEnvironment env;
+ env->ExceptionClear(); // just in case
+ qCWarning(QT_BT_ANDROID) << "Workaround failed";
+ }
+}
+
+void QBluetoothSocketPrivate::fallbackSocketConnectFailed(
+ const QAndroidJniObject &socket, const QAndroidJniObject &targetUuid)
+{
+ Q_UNUSED(targetUuid);
+ Q_Q(QBluetoothSocket);
+
+ // test we didn't get a fail from a previous connect
+ // which was cleaned up late - should be same socket
+ if (socket != socketObject)
+ return;
+
+ qCWarning(QT_BT_ANDROID) << "Socket connect via workaround failed.";
+ errorString = QBluetoothSocket::tr("Connection to service failed");
+ socketObject = remoteDevice = QAndroidJniObject();
+
+ q->setSocketError(QBluetoothSocket::ServiceNotFoundError);
+ q->setSocketState(QBluetoothSocket::UnconnectedState);
+}
+
void QBluetoothSocketPrivate::abort()
{
if (state == QBluetoothSocket::UnconnectedState)
@@ -356,23 +514,26 @@ void QBluetoothSocketPrivate::abort()
if (inputThread)
inputThread->prepareForClosure();
- //triggers abort of input thread as well
- socketObject.callMethod<void>("close");
- if (env->ExceptionCheck()) {
+ emit closeJavaSocket();
- qCWarning(QT_BT_ANDROID) << "Error during closure of socket";
- env->ExceptionDescribe();
- env->ExceptionClear();
- }
+ inputStream = outputStream = socketObject = remoteDevice = QAndroidJniObject();
if (inputThread) {
+ // inputThread exists hence we had a successful connect
+ // which means inputThread is responsible for setting Unconnected
+
//don't delete here as signals caused by Java Thread are still
//going to be emitted
//delete occurs in inputThreadError()
inputThread = 0;
+ } else {
+ // inputThread doesn't exist hence
+ // we abort in the middle of connect(). WorkerThread will do
+ // close() without further feedback. Therefore we have to set
+ // Unconnected (now) in advance
+ Q_Q(QBluetoothSocket);
+ q->setSocketState(QBluetoothSocket::UnconnectedState);
}
-
- inputStream = outputStream = socketObject = remoteDevice = QAndroidJniObject();
}
}
@@ -486,14 +647,13 @@ void QBluetoothSocketPrivate::inputThreadError(int errorCode)
//cleanup internal objects
//if it was call to local close()/abort() the objects are cleaned up already
- QAndroidJniEnvironment env;
- socketObject.callMethod<void>("close");
- if (env->ExceptionCheck()) {
- env->ExceptionDescribe();
- env->ExceptionClear();
- }
+ emit closeJavaSocket();
inputStream = outputStream = remoteDevice = socketObject = QAndroidJniObject();
+ if (inputThread) {
+ // deleted already above (client->deleteLater())
+ inputThread = 0;
+ }
}
q->setSocketState(QBluetoothSocket::UnconnectedState);
@@ -575,6 +735,14 @@ bool QBluetoothSocketPrivate::setSocketDescriptor(const QAndroidJniObject &socke
q->setSocketState(socketState);
q->setOpenMode(openMode | QIODevice::Unbuffered);
+ // WorkerThread manages all sockets for us
+ // When we come through here the socket was already connected by
+ // server socket listener (see QBluetoothServer)
+ // Therefore we only use WorkerThread to potentially close it later on
+ WorkerThread *workerThread = new WorkerThread();
+ workerThread->setupWorker(this, socketObject, QAndroidJniObject(), !USE_FALLBACK);
+ workerThread->start();
+
if (openMode == QBluetoothSocket::ConnectedState)
emit q->connected();
@@ -591,3 +759,5 @@ qint64 QBluetoothSocketPrivate::bytesAvailable() const
}
QT_END_NAMESPACE
+
+#include <qbluetoothsocket_android.moc>
diff --git a/src/bluetooth/qbluetoothsocket_bluez.cpp b/src/bluetooth/qbluetoothsocket_bluez.cpp
index 47f5629e..c18ce279 100644
--- a/src/bluetooth/qbluetoothsocket_bluez.cpp
+++ b/src/bluetooth/qbluetoothsocket_bluez.cpp
@@ -511,20 +511,10 @@ qint64 QBluetoothSocketPrivate::readData(char *data, qint64 maxSize)
void QBluetoothSocketPrivate::close()
{
- Q_Q(QBluetoothSocket);
-
- // Only go through closing if the socket was fully opened
- if(state == QBluetoothSocket::ConnectedState)
- q->setSocketState(QBluetoothSocket::ClosingState);
-
- if(txBuffer.size() > 0 &&
- state == QBluetoothSocket::ClosingState){
+ if (txBuffer.size() > 0)
connectWriteNotifier->setEnabled(true);
- }
- else {
+ else
abort();
- }
-
}
bool QBluetoothSocketPrivate::setSocketDescriptor(int socketDescriptor, QBluetoothServiceInfo::Protocol socketType_,
diff --git a/src/bluetooth/qbluetoothsocket_p.h b/src/bluetooth/qbluetoothsocket_p.h
index 40bc678f..e5ddf798 100644
--- a/src/bluetooth/qbluetoothsocket_p.h
+++ b/src/bluetooth/qbluetoothsocket_p.h
@@ -52,8 +52,10 @@
#endif
#ifdef QT_ANDROID_BLUETOOTH
#include <QtAndroidExtras/QAndroidJniObject>
+#include <QtCore/QPointer>
#include "android/inputstreamthread_p.h"
#include <jni.h>
+class WorkerThread;
#endif
#ifndef QPRIVATELINEARBUFFER_BUFFERSIZE
@@ -94,18 +96,14 @@ public:
~QBluetoothSocketPrivate();
//On QNX and Android we connect using the uuid not the port
-#if defined(QT_QNX_BLUETOOTH)
- void connectToService(const QBluetoothAddress &address, const QBluetoothUuid &uuid, QIODevice::OpenMode openMode);
-#elif defined(QT_ANDROID_BLUETOOTH)
+#if defined(QT_QNX_BLUETOOTH) || defined(QT_ANDROID_BLUETOOTH)
void connectToService(const QBluetoothAddress &address, const QBluetoothUuid &uuid,
- QIODevice::OpenMode openMode, int fallbackServiceChannel = 1);
- bool fallBackConnect(QAndroidJniObject uuid, int channel);
+ QIODevice::OpenMode openMode);
#else
void connectToService(const QBluetoothAddress &address, quint16 port, QIODevice::OpenMode openMode);
#endif
#ifdef QT_ANDROID_BLUETOOTH
- void connectToServiceConc(const QBluetoothAddress &address, const QBluetoothUuid &uuid,
- QIODevice::OpenMode openMode, int fallbackServiceChannel = 1);
+ bool fallBackConnect(QAndroidJniObject uuid, int channel);
#endif
@@ -167,9 +165,18 @@ public:
QAndroidJniObject outputStream;
InputStreamThread *inputThread;
-private slots:
+public slots:
+ void socketConnectSuccess(const QAndroidJniObject &socket);
+ void defaultSocketConnectFailed(const QAndroidJniObject & socket,
+ const QAndroidJniObject &targetUuid);
+ void fallbackSocketConnectFailed(const QAndroidJniObject &socket,
+ const QAndroidJniObject &targetUuid);
void inputThreadError(int errorCode);
+signals:
+ void connectJavaSocket();
+ void closeJavaSocket();
+
#endif
#if defined(QT_QNX_BLUETOOTH) || defined(QT_BLUEZ_BLUETOOTH)
diff --git a/src/bluetooth/qlowenergycontroller_bluez.cpp b/src/bluetooth/qlowenergycontroller_bluez.cpp
index 2d4fa7be..d355b070 100644
--- a/src/bluetooth/qlowenergycontroller_bluez.cpp
+++ b/src/bluetooth/qlowenergycontroller_bluez.cpp
@@ -79,6 +79,7 @@
#define ATT_OP_WRITE_COMMAND 0x52 //write characteristic without response
//GATT command sizes in bytes
+#define ERROR_RESPONSE_HEADER_SIZE 5
#define FIND_INFO_REQUEST_HEADER_SIZE 5
#define GRP_TYPE_REQ_HEADER_SIZE 7
#define READ_BY_TYPE_REQ_HEADER_SIZE 7
@@ -358,9 +359,20 @@ void QLowEnergyControllerPrivate::l2cpReadyRead()
case ATT_OP_READ_REQUEST:
case ATT_OP_FIND_INFORMATION_REQUEST:
case ATT_OP_WRITE_REQUEST:
- qCWarning(QT_BT_BLUEZ) << "Unexpected message type" << hex << command
- << "will be ignored" ;
+ {
+ qCDebug(QT_BT_BLUEZ) << "Server request" << hex << command;
+
+ //send not supported
+ QByteArray packet(ERROR_RESPONSE_HEADER_SIZE, Qt::Uninitialized);
+ packet[0] = ATT_OP_ERROR_RESPONSE;
+ packet[1] = command;
+ bt_put_unaligned(htobs(0), (quint16 *)(packet.data() + 2));
+ packet[4] = ATT_ERROR_REQUEST_NOT_SUPPORTED;
+
+ sendCommand(packet);
+
return;
+ }
default:
//only solicited replies finish pending requests
requestPending = false;
@@ -386,10 +398,12 @@ void QLowEnergyControllerPrivate::l2cpReadyRead()
void QLowEnergyControllerPrivate::encryptionChangedEvent(
const QBluetoothAddress &address, bool wasSuccess)
{
+ if (!encryptionChangePending) // somebody else caused change event
+ return;
+
if (remoteDevice != address)
return;
- Q_ASSERT(encryptionChangePending);
securityLevelValue = securityLevel();
// On success continue to process ATT command queue