summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorTarja Sundqvist <tarja.sundqvist@qt.io>2023-04-24 10:13:37 +0300
committerTarja Sundqvist <tarja.sundqvist@qt.io>2023-04-24 10:13:37 +0300
commitda6113cb52beb5731d8c95ecbfc375936f59def2 (patch)
tree81a617b98e6e04d660fb2e75aae942a49ed7c2a1
parent3dcb548bd6fe4aa488ca0bac95e65a7a366c3eca (diff)
parentca96a42035255b4355e4d8ddba7f5da7b9006577 (diff)
Merge remote-tracking branch 'origin/tqtc/lts-5.15.10' into tqtc/lts-5.15-opensource
-rw-r--r--.qmake.conf2
-rw-r--r--src/android/bluetooth/src/org/qtproject/qt5/android/bluetooth/QtBluetoothBroadcastReceiver.java49
-rw-r--r--src/android/bluetooth/src/org/qtproject/qt5/android/bluetooth/QtBluetoothSocketServer.java25
-rw-r--r--src/bluetooth/android/android.pri6
-rw-r--r--src/bluetooth/android/androidutils.cpp89
-rw-r--r--src/bluetooth/android/androidutils_p.h71
-rw-r--r--src/bluetooth/bluetooth.pro12
-rw-r--r--src/bluetooth/bluez/bluetoothmanagement.cpp2
-rw-r--r--src/bluetooth/bluez/bluez5_helper.cpp2
-rw-r--r--src/bluetooth/bluez/hcimanager.cpp2
-rw-r--r--src/bluetooth/bluez/profile1context.cpp2
-rw-r--r--src/bluetooth/bluez/remotedevicemanager.cpp2
-rw-r--r--src/bluetooth/qbluetoothdevicediscoveryagent_android.cpp10
-rw-r--r--src/bluetooth/qbluetoothdevicediscoveryagent_p.cpp2
-rw-r--r--src/bluetooth/qbluetoothlocaldevice.cpp23
-rw-r--r--src/bluetooth/qbluetoothlocaldevice_android.cpp124
-rw-r--r--src/bluetooth/qbluetoothlocaldevice_p.h2
-rw-r--r--src/bluetooth/qbluetoothserver_android.cpp12
-rw-r--r--src/bluetooth/qbluetoothservicediscoveryagent_android.cpp52
-rw-r--r--src/bluetooth/qbluetoothservicediscoveryagent_p.cpp2
-rw-r--r--src/bluetooth/qbluetoothserviceinfo_android.cpp10
-rw-r--r--src/bluetooth/qbluetoothserviceinfo_p.cpp2
-rw-r--r--src/bluetooth/qbluetoothsocket_android.cpp28
-rw-r--r--src/bluetooth/qbluetoothsocket_bluez.cpp2
-rw-r--r--src/bluetooth/qbluetoothsocket_bluezdbus.cpp2
-rw-r--r--src/bluetooth/qbluetoothsocket_osx.mm2
-rw-r--r--src/bluetooth/qbluetoothsocketbase.cpp2
-rw-r--r--src/bluetooth/qleadvertiser_bluez.cpp4
-rw-r--r--src/bluetooth/qleadvertiser_bluez_p.h (renamed from src/bluetooth/qleadvertiser_p.h)12
-rw-r--r--src/bluetooth/qlowenergyadvertisingdata.h2
-rw-r--r--src/bluetooth/qlowenergyadvertisingparameters.h2
-rw-r--r--src/bluetooth/qlowenergycharacteristicdata.h2
-rw-r--r--src/bluetooth/qlowenergyconnectionparameters.h2
-rw-r--r--src/bluetooth/qlowenergycontroller.cpp16
-rw-r--r--src/bluetooth/qlowenergycontroller_android.cpp26
-rw-r--r--src/bluetooth/qlowenergycontroller_android_p.h2
-rw-r--r--src/bluetooth/qlowenergycontroller_bluez.cpp4
-rw-r--r--src/bluetooth/qlowenergycontroller_bluezdbus.cpp64
-rw-r--r--src/bluetooth/qlowenergycontrollerbase.cpp2
-rw-r--r--src/bluetooth/qlowenergydescriptordata.h2
-rw-r--r--src/bluetooth/qlowenergyservice.cpp2
-rw-r--r--src/bluetooth/qlowenergyservicedata.h2
-rw-r--r--src/bluetooth/qlowenergyserviceprivate.cpp2
-rw-r--r--src/nfc/qnearfieldmanager.cpp4
-rw-r--r--src/nfc/qnearfieldtarget.cpp2
-rw-r--r--tests/auto/qbluetoothservicediscoveryagent/tst_qbluetoothservicediscoveryagent.cpp19
46 files changed, 593 insertions, 117 deletions
diff --git a/.qmake.conf b/.qmake.conf
index 213056f5..5e6fec74 100644
--- a/.qmake.conf
+++ b/.qmake.conf
@@ -2,4 +2,4 @@ load(qt_build_config)
DEFINES += QT_NO_FOREACH QT_NO_JAVA_STYLE_ITERATORS QT_NO_LINKED_LIST
-MODULE_VERSION = 5.15.9
+MODULE_VERSION = 5.15.10
diff --git a/src/android/bluetooth/src/org/qtproject/qt5/android/bluetooth/QtBluetoothBroadcastReceiver.java b/src/android/bluetooth/src/org/qtproject/qt5/android/bluetooth/QtBluetoothBroadcastReceiver.java
index 6b46ec0a..3d2f1ad9 100644
--- a/src/android/bluetooth/src/org/qtproject/qt5/android/bluetooth/QtBluetoothBroadcastReceiver.java
+++ b/src/android/bluetooth/src/org/qtproject/qt5/android/bluetooth/QtBluetoothBroadcastReceiver.java
@@ -61,8 +61,15 @@ public class QtBluetoothBroadcastReceiver extends BroadcastReceiver
@SuppressWarnings("WeakerAccess")
static Context qtContext = null;
- private static final int TURN_BT_ON = 3330;
+ // These are opaque tokens that could be used to match the completed action
+ private static final int TURN_BT_ENABLED = 3330;
private static final int TURN_BT_DISCOVERABLE = 3331;
+ private static final int TURN_BT_DISABLED = 3332;
+
+ // The 'Disable' action identifier is hidden in the public APIs so we define it here
+ public static final String ACTION_REQUEST_DISABLE =
+ "android.bluetooth.adapter.action.REQUEST_DISABLE";
+
private static final String TAG = "QtBluetoothBroadcastReceiver";
public void onReceive(Context context, Intent intent)
@@ -90,35 +97,61 @@ public class QtBluetoothBroadcastReceiver extends BroadcastReceiver
qtContext = context;
}
- static public void setDiscoverable()
+ static public boolean setDisabled()
+ {
+ if (!(qtContext instanceof android.app.Activity)) {
+ Log.w(TAG, "Bluetooth cannot be disabled from a service.");
+ return false;
+ }
+ // The 'disable' is hidden in the public API and as such
+ // there are no availability guarantees; may throw an "ActivityNotFoundException"
+ Intent intent = new Intent(ACTION_REQUEST_DISABLE);
+
+ try {
+ ((Activity)qtContext).startActivityForResult(intent, TURN_BT_DISABLED);
+ } catch (Exception ex) {
+ Log.w(TAG, "setDisabled() failed to initiate Bluetooth disablement");
+ ex.printStackTrace();
+ return false;
+ }
+ return true;
+ }
+
+ static public boolean setDiscoverable()
{
if (!(qtContext instanceof android.app.Activity)) {
Log.w(TAG, "Discovery mode cannot be enabled from a service.");
- return;
+ return false;
}
Intent intent = new Intent(BluetoothAdapter.ACTION_REQUEST_DISCOVERABLE);
intent.putExtra(BluetoothAdapter.EXTRA_DISCOVERABLE_DURATION, 300);
try {
- ((Activity)qtContext).startActivityForResult(intent, TURN_BT_ON);
+ ((Activity)qtContext).startActivityForResult(intent, TURN_BT_DISCOVERABLE);
} catch (Exception ex) {
+ Log.w(TAG, "setDisabled() failed to initiate Bluetooth discoverability change");
ex.printStackTrace();
+ return false;
}
+ return true;
}
- static public void setConnectable()
+ static public boolean setEnabled()
{
if (!(qtContext instanceof android.app.Activity)) {
- Log.w(TAG, "Connectable mode cannot be enabled from a service.");
- return;
+ Log.w(TAG, "Bluetooth cannot be enabled from a service.");
+ return false;
}
Intent intent = new Intent(BluetoothAdapter.ACTION_REQUEST_ENABLE);
try {
- ((Activity)qtContext).startActivityForResult(intent, TURN_BT_DISCOVERABLE);
+ ((Activity)qtContext).startActivityForResult(intent, TURN_BT_ENABLED);
} catch (Exception ex) {
+ Log.w(TAG, "setEnabled() failed to initiate Bluetooth enablement");
ex.printStackTrace();
+ return false;
}
+ return true;
}
static public boolean setPairingMode(String address, boolean isPairing)
diff --git a/src/android/bluetooth/src/org/qtproject/qt5/android/bluetooth/QtBluetoothSocketServer.java b/src/android/bluetooth/src/org/qtproject/qt5/android/bluetooth/QtBluetoothSocketServer.java
index a10b1f62..f9337611 100644
--- a/src/android/bluetooth/src/org/qtproject/qt5/android/bluetooth/QtBluetoothSocketServer.java
+++ b/src/android/bluetooth/src/org/qtproject/qt5/android/bluetooth/QtBluetoothSocketServer.java
@@ -106,6 +106,9 @@ public class QtBluetoothSocketServer extends Thread
return;
}
+ if (isInterrupted()) // close() may have been called
+ return;
+
BluetoothSocket s;
if (m_serverSocket != null) {
try {
@@ -131,6 +134,24 @@ public class QtBluetoothSocketServer extends Thread
Log.d(TAG, "Leaving server socket thread.");
}
+ // This function closes the socket server
+ //
+ // A note on threading behavior
+ // 1. This function is called from Qt thread which is different from the Java thread (run())
+ // 2. The caller of this function expects the Java thread to be finished upon return
+ //
+ // First we mark the Java thread as interrupted, then call close() on the
+ // listening socket if it had been created, and lastly wait for the thread to finish.
+ // The close() method of the socket is intended to be used to abort the accept() from
+ // another thread, as per the accept() documentation.
+ //
+ // If the Java thread was in the middle of creating a socket with the non-blocking
+ // listen* call, the run() will notice after the returning from the listen* that it has
+ // been interrupted and returns early from the run().
+ //
+ // If the Java thread was in the middle of the blocking accept() call, it will get
+ // interrupated by the close() call on the socket. After returning the run() will
+ // notice it has been interrupted and return from the run()
public void close()
{
if (!isAlive())
@@ -143,7 +164,9 @@ public class QtBluetoothSocketServer extends Thread
//interrupts accept() call above
if (m_serverSocket != null)
m_serverSocket.close();
- } catch (IOException ex) {
+ // Wait for the thread to finish
+ join(20); // Maximum wait in ms, typically takes < 1ms
+ } catch (Exception ex) {
Log.d(TAG, "Closing server socket close() failed:" + ex.toString());
ex.printStackTrace();
}
diff --git a/src/bluetooth/android/android.pri b/src/bluetooth/android/android.pri
index af39a6d7..8ba98c74 100644
--- a/src/bluetooth/android/android.pri
+++ b/src/bluetooth/android/android.pri
@@ -6,7 +6,8 @@ HEADERS += \
android/localdevicebroadcastreceiver_p.h \
android/serveracceptancethread_p.h \
android/jni_android_p.h \
- android/lowenergynotificationhub_p.h
+ android/lowenergynotificationhub_p.h \
+ android/androidutils_p.h
SOURCES += \
@@ -17,4 +18,5 @@ SOURCES += \
android/androidbroadcastreceiver.cpp \
android/localdevicebroadcastreceiver.cpp \
android/serveracceptancethread.cpp \
- android/lowenergynotificationhub.cpp
+ android/lowenergynotificationhub.cpp \
+ android/androidutils.cpp
diff --git a/src/bluetooth/android/androidutils.cpp b/src/bluetooth/android/androidutils.cpp
new file mode 100644
index 00000000..ec4dce8a
--- /dev/null
+++ b/src/bluetooth/android/androidutils.cpp
@@ -0,0 +1,89 @@
+/****************************************************************************
+**
+** Copyright (C) 2022 The Qt Company Ltd.
+** Contact: https://www.qt.io/licensing/
+**
+** This file is part of the QtBluetooth module of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:COMM$
+**
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and The Qt Company. For licensing terms
+** and conditions see https://www.qt.io/terms-conditions. For further
+** information use the contact form at https://www.qt.io/contact-us.
+**
+** $QT_END_LICENSE$
+**
+**
+**
+**
+**
+**
+**
+**
+**
+**
+**
+**
+**
+**
+**
+**
+**
+**
+**
+****************************************************************************/
+
+#include "androidutils_p.h"
+
+#include <QtCore/QLoggingCategory>
+#include <QtAndroidExtras/QAndroidJniEnvironment>
+#include <QtCore/private/qjnihelpers_p.h>
+
+QT_BEGIN_NAMESPACE
+
+Q_DECLARE_LOGGING_CATEGORY(QT_BT_ANDROID)
+
+static QString androidPermissionString(BluetoothPermission permission)
+{
+ switch (permission) {
+ case BluetoothPermission::Scan:
+ return {QStringLiteral("android.permission.BLUETOOTH_SCAN")};
+ case BluetoothPermission::Advertise:
+ return {QStringLiteral("android.permission.BLUETOOTH_ADVERTISE")};
+ case BluetoothPermission::Connect:
+ return {QStringLiteral("android.permission.BLUETOOTH_CONNECT")};
+ }
+ return {};
+}
+
+bool ensureAndroidPermission(BluetoothPermission permission)
+{
+ // The current set of permissions are only applicable with 31+
+ if (QtAndroidPrivate::androidSdkVersion() < 31)
+ return true;
+
+ const auto permString = androidPermissionString(permission);
+
+ // First check if we have the permission already
+ if (QtAndroidPrivate::checkPermission(permString)
+ == QtAndroidPrivate::PermissionsResult::Granted) {
+ return true;
+ }
+
+ // If we didn't have the permission, request it
+ QAndroidJniEnvironment env;
+ auto result = QtAndroidPrivate::requestPermissionsSync(env, QStringList() << permString);
+ if (result.contains(permString)
+ && result[permString] == QtAndroidPrivate::PermissionsResult::Granted) {
+ return true;
+ }
+
+ qCWarning(QT_BT_ANDROID) << "Permission not authorized:" << permString;
+ return false;
+}
+
+QT_END_NAMESPACE
diff --git a/src/bluetooth/android/androidutils_p.h b/src/bluetooth/android/androidutils_p.h
new file mode 100644
index 00000000..2e2f6141
--- /dev/null
+++ b/src/bluetooth/android/androidutils_p.h
@@ -0,0 +1,71 @@
+/****************************************************************************
+**
+** Copyright (C) 2022 The Qt Company Ltd.
+** Contact: https://www.qt.io/licensing/
+**
+** This file is part of the QtBluetooth module of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:COMM$
+**
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and The Qt Company. For licensing terms
+** and conditions see https://www.qt.io/terms-conditions. For further
+** information use the contact form at https://www.qt.io/contact-us.
+**
+** $QT_END_LICENSE$
+**
+**
+**
+**
+**
+**
+**
+**
+**
+**
+**
+**
+**
+**
+**
+**
+**
+**
+**
+****************************************************************************/
+
+#ifndef QANDROIDBLUETOOTHUTILS_H
+#define QANDROIDBLUETOOTHUTILS_H
+
+//
+// W A R N I N G
+// -------------
+//
+// This file is not part of the Qt API. It exists purely as an
+// implementation detail. This header file may change from version to
+// version without notice, or even be removed.
+//
+// We mean it.
+//
+
+#include <qglobal.h>
+#include <QtCore/QString>
+
+QT_BEGIN_NAMESPACE
+
+enum class BluetoothPermission {
+ Scan,
+ Advertise,
+ Connect
+};
+
+// Checks if a permssion is already authorized and requests if not.
+// Returns true if permission is successfully authorized
+bool ensureAndroidPermission(BluetoothPermission permission);
+
+QT_END_NAMESPACE
+
+#endif // QANDROIDBLUETOOTHUTILS_H
diff --git a/src/bluetooth/bluetooth.pro b/src/bluetooth/bluetooth.pro
index 9f42b34e..b7f9a198 100644
--- a/src/bluetooth/bluetooth.pro
+++ b/src/bluetooth/bluetooth.pro
@@ -46,7 +46,6 @@ HEADERS += \
qbluetoothlocaldevice_p.h \
qlowenergycontrollerbase_p.h \
qlowenergyserviceprivate_p.h \
- qleadvertiser_p.h \
lecmaccalculator_p.h
SOURCES += \
@@ -116,8 +115,10 @@ qtConfig(bluez) {
lecmaccalculator.cpp \
qlowenergycontroller_bluezdbus.cpp
- HEADERS += qlowenergycontroller_bluezdbus_p.h \
- qlowenergycontroller_bluez_p.h
+ HEADERS += \
+ qleadvertiser_bluez_p.h \
+ qlowenergycontroller_bluezdbus_p.h \
+ qlowenergycontroller_bluez_p.h
qtConfig(linux_crypto_api): DEFINES += CONFIG_LINUX_CRYPTO_API
} else {
@@ -138,7 +139,10 @@ qtConfig(bluez) {
android.permission.BLUETOOTH \
android.permission.BLUETOOTH_ADMIN \
android.permission.ACCESS_FINE_LOCATION \
- android.permission.ACCESS_COARSE_LOCATION # since Android 6.0 (API lvl 23)
+ android.permission.ACCESS_COARSE_LOCATION \ # since Android 6.0 (API lvl 23)
+ android.permission.BLUETOOTH_SCAN \ # since Android 12.0 (API lvl 31)
+ android.permission.BLUETOOTH_ADVERTISE \ # since Android 12.0 (API lvl 31)
+ android.permission.BLUETOOTH_CONNECT # since Android 12.0 (API lvl 31)
ANDROID_BUNDLED_JAR_DEPENDENCIES = \
jar/QtAndroidBluetooth.jar:org.qtproject.qt5.android.bluetooth.QtBluetoothBroadcastReceiver
diff --git a/src/bluetooth/bluez/bluetoothmanagement.cpp b/src/bluetooth/bluez/bluetoothmanagement.cpp
index b6ad93e5..62d32238 100644
--- a/src/bluetooth/bluez/bluetoothmanagement.cpp
+++ b/src/bluetooth/bluez/bluetoothmanagement.cpp
@@ -313,3 +313,5 @@ bool BluetoothManagement::isMonitoringEnabled() const
QT_END_NAMESPACE
+
+#include "moc_bluetoothmanagement_p.cpp"
diff --git a/src/bluetooth/bluez/bluez5_helper.cpp b/src/bluetooth/bluez/bluez5_helper.cpp
index 58da1ed3..e06df356 100644
--- a/src/bluetooth/bluez/bluez5_helper.cpp
+++ b/src/bluetooth/bluez/bluez5_helper.cpp
@@ -577,3 +577,5 @@ QString sanitizeNameForDBus(const QString &text)
}
QT_END_NAMESPACE
+
+#include "moc_bluez5_helper_p.cpp"
diff --git a/src/bluetooth/bluez/hcimanager.cpp b/src/bluetooth/bluez/hcimanager.cpp
index a8b8e3b9..0f5c6510 100644
--- a/src/bluetooth/bluez/hcimanager.cpp
+++ b/src/bluetooth/bluez/hcimanager.cpp
@@ -599,3 +599,5 @@ void HciManager::handleLeMetaEvent(const quint8 *data)
}
QT_END_NAMESPACE
+
+#include "moc_hcimanager_p.cpp"
diff --git a/src/bluetooth/bluez/profile1context.cpp b/src/bluetooth/bluez/profile1context.cpp
index 5eeec56a..912b36b2 100644
--- a/src/bluetooth/bluez/profile1context.cpp
+++ b/src/bluetooth/bluez/profile1context.cpp
@@ -70,3 +70,5 @@ void OrgBluezProfile1ContextInterface::Release()
}
QT_END_NAMESPACE
+
+#include "moc_profile1context_p.cpp"
diff --git a/src/bluetooth/bluez/remotedevicemanager.cpp b/src/bluetooth/bluez/remotedevicemanager.cpp
index 5d17d571..5377724a 100644
--- a/src/bluetooth/bluez/remotedevicemanager.cpp
+++ b/src/bluetooth/bluez/remotedevicemanager.cpp
@@ -171,3 +171,5 @@ void RemoteDeviceManager::disconnectDevice(const QBluetoothAddress &remote)
}
QT_END_NAMESPACE
+
+#include "moc_remotedevicemanager_p.cpp"
diff --git a/src/bluetooth/qbluetoothdevicediscoveryagent_android.cpp b/src/bluetooth/qbluetoothdevicediscoveryagent_android.cpp
index 53acd2d1..228c8bb3 100644
--- a/src/bluetooth/qbluetoothdevicediscoveryagent_android.cpp
+++ b/src/bluetooth/qbluetoothdevicediscoveryagent_android.cpp
@@ -38,6 +38,7 @@
**
****************************************************************************/
+#include "android/androidutils_p.h"
#include "qbluetoothdevicediscoveryagent_p.h"
#include <QtCore/QLoggingCategory>
#include <QtBluetooth/QBluetoothAddress>
@@ -220,6 +221,15 @@ void QBluetoothDeviceDiscoveryAgentPrivate::start(QBluetoothDeviceDiscoveryAgent
qCDebug(QT_BT_ANDROID) << "Location turned on";
+ if (!(ensureAndroidPermission(BluetoothPermission::Scan) &&
+ ensureAndroidPermission(BluetoothPermission::Connect))) {
+ qCWarning(QT_BT_ANDROID) << "Device discovery start() failed due to missing permissions";
+ errorString = QBluetoothDeviceDiscoveryAgent::tr("Bluetooth adapter error");
+ lastError = QBluetoothDeviceDiscoveryAgent::UnknownError;
+ emit q->error(lastError);
+ return;
+ }
+
// install Java BroadcastReceiver
if (!receiver) {
// SDP based device discovery
diff --git a/src/bluetooth/qbluetoothdevicediscoveryagent_p.cpp b/src/bluetooth/qbluetoothdevicediscoveryagent_p.cpp
index e3646db9..ba9a83d0 100644
--- a/src/bluetooth/qbluetoothdevicediscoveryagent_p.cpp
+++ b/src/bluetooth/qbluetoothdevicediscoveryagent_p.cpp
@@ -90,3 +90,5 @@ void QBluetoothDeviceDiscoveryAgentPrivate::stop()
QT_END_NAMESPACE
+
+#include "moc_qbluetoothdevicediscoveryagent_p.cpp"
diff --git a/src/bluetooth/qbluetoothlocaldevice.cpp b/src/bluetooth/qbluetoothlocaldevice.cpp
index 38dd56f4..342fab92 100644
--- a/src/bluetooth/qbluetoothlocaldevice.cpp
+++ b/src/bluetooth/qbluetoothlocaldevice.cpp
@@ -104,6 +104,16 @@ QT_BEGIN_NAMESPACE
be connectable and powered on, if required. This mode is is not supported on Android.
On \macos, it is not possible to set the \l hostMode() to HostConnectable or HostPoweredOff.
+ \note Starting from Android 13 (API level 33) the HostPoweredOff state relies on
+ non-public Android API as the public one has been deprecated, see
+ (\l {https://developer.android.com/reference/android/bluetooth/BluetoothAdapter#disable()}
+ {disable()}). This may change in a future version of Android.
+
+ \note At least on Android 12 the device's Bluetooth visibility setting may dictate the result
+ of setting either HostDiscoverable or HostConnectable. For example if the visibility is set
+ \e off, it may not be possible to enter the HostDiscoverable mode, but HostConnectable will be
+ used instead. This may change in future version of Android.
+
*/
void registerQBluetoothLocalDeviceMetaType()
@@ -137,6 +147,13 @@ QBluetoothLocalDevice::~QBluetoothLocalDevice()
remains invalid even if the same Bluetooth adapter is returned to
the system.
+//! [android-permissions-valid]
+ \note Starting from Android 12 (API level 31), the construction of this class requires
+ \l {https://developer.android.com/guide/topics/connectivity/bluetooth/permissions}
+ {bluetooth runtime permissions} (\e BLUETOOTH_SCAN and \e BLUETOOTH_CONNECT). If the
+ permissions are not granted, the device will not be valid.
+//! [android-permissions-valid]
+
\sa allDevices()
*/
bool QBluetoothLocalDevice::isValid() const
@@ -206,6 +223,9 @@ bool QBluetoothLocalDevice::isValid() const
/*!
\fn QBluetoothLocalDevice::QBluetoothLocalDevice(QObject *parent)
Constructs a QBluetoothLocalDevice with \a parent.
+
+ \include qbluetoothlocaldevice.cpp android-permissions-valid
+ \sa isValid()
*/
/*!
@@ -324,6 +344,9 @@ bool QBluetoothLocalDevice::isValid() const
Construct new QBluetoothLocalDevice for \a address. If \a address is default constructed
the resulting local device selects the local default device.
+
+ \include qbluetoothlocaldevice.cpp android-permissions-valid
+ \sa isValid()
*/
QT_END_NAMESPACE
diff --git a/src/bluetooth/qbluetoothlocaldevice_android.cpp b/src/bluetooth/qbluetoothlocaldevice_android.cpp
index 2995d368..cd14211a 100644
--- a/src/bluetooth/qbluetoothlocaldevice_android.cpp
+++ b/src/bluetooth/qbluetoothlocaldevice_android.cpp
@@ -38,6 +38,9 @@
**
****************************************************************************/
+#include "android/androidutils_p.h"
+#include "android/localdevicebroadcastreceiver_p.h"
+#include "qbluetoothlocaldevice_p.h"
#include <QtCore/QLoggingCategory>
#include <QtCore/private/qjnihelpers_p.h>
#include <QtAndroidExtras/QAndroidJniEnvironment>
@@ -45,9 +48,6 @@
#include <QtBluetooth/QBluetoothLocalDevice>
#include <QtBluetooth/QBluetoothAddress>
-#include "qbluetoothlocaldevice_p.h"
-#include "android/localdevicebroadcastreceiver_p.h"
-
QT_BEGIN_NAMESPACE
Q_DECLARE_LOGGING_CATEGORY(QT_BT_ANDROID)
@@ -110,6 +110,12 @@ void QBluetoothLocalDevicePrivate::initialize(const QBluetoothAddress &address)
return;
}
+ if (!(ensureAndroidPermission(BluetoothPermission::Scan) &&
+ ensureAndroidPermission(BluetoothPermission::Connect))) {
+ qCWarning(QT_BT_ANDROID) << "Local device initialize() failed due to missing permissions";
+ return;
+ }
+
obj = new QAndroidJniObject(adapter);
if (!address.isNull()) {
const QString localAddress
@@ -129,19 +135,26 @@ bool QBluetoothLocalDevicePrivate::isValid() const
void QBluetoothLocalDevicePrivate::processHostModeChange(QBluetoothLocalDevice::HostMode newMode)
{
- if (!pendingHostModeTransition) {
- // if not in transition -> pass data on
+ qCDebug(QT_BT_ANDROID) << "Processing host mode change:" << newMode
+ << ", pending transition:" << pendingConnectableHostModeTransition;
+ if (!pendingConnectableHostModeTransition) {
+ // If host mode is not in transition -> pass data on
emit q_ptr->hostModeStateChanged(newMode);
return;
}
+ // Host mode is in transition: check if the new mode is 'off' in which state
+ // we can enter the targeted 'Connectable' state
if (isValid() && newMode == QBluetoothLocalDevice::HostPoweredOff) {
- bool success = (bool)obj->callMethod<jboolean>("enable", "()Z");
- if (!success)
+ const bool success = (bool)QAndroidJniObject::callStaticMethod<jboolean>(
+ "org/qtproject/qt5/android/bluetooth/QtBluetoothBroadcastReceiver",
+ "setEnabled");
+ if (!success) {
+ qCWarning(QT_BT_ANDROID) << "Transitioning Bluetooth from OFF to ON failed";
emit q_ptr->error(QBluetoothLocalDevice::UnknownError);
+ }
}
-
- pendingHostModeTransition = false;
+ pendingConnectableHostModeTransition = false;
}
// Return -1 if address is not part of a pending pairing request
@@ -245,44 +258,87 @@ void QBluetoothLocalDevice::powerOn()
return;
if (d_ptr->adapter()) {
- bool ret = (bool)d_ptr->adapter()->callMethod<jboolean>("enable", "()Z");
- if (!ret)
+ bool success(false);
+ if (QtAndroidPrivate::androidSdkVersion() >= 31) {
+ success = (bool)QAndroidJniObject::callStaticMethod<jboolean>(
+ "org/qtproject/qt5/android/bluetooth/QtBluetoothBroadcastReceiver",
+ "setEnabled");
+ } else {
+ success = (bool)d_ptr->adapter()->callMethod<jboolean>("enable", "()Z");
+ }
+ if (!success) {
+ qCWarning(QT_BT_ANDROID) << "Enabling bluetooth failed";
emit error(QBluetoothLocalDevice::UnknownError);
+ }
}
}
void QBluetoothLocalDevice::setHostMode(QBluetoothLocalDevice::HostMode requestedMode)
{
- QBluetoothLocalDevice::HostMode mode = requestedMode;
+ QBluetoothLocalDevice::HostMode nextMode = requestedMode;
if (requestedMode == HostDiscoverableLimitedInquiry)
- mode = HostDiscoverable;
+ nextMode = HostDiscoverable;
- if (mode == hostMode())
+ if (nextMode == hostMode())
return;
- if (mode == QBluetoothLocalDevice::HostPoweredOff) {
- bool success = false;
- if (d_ptr->adapter())
- success = (bool)d_ptr->adapter()->callMethod<jboolean>("disable", "()Z");
+ switch (nextMode) {
- if (!success)
+ case QBluetoothLocalDevice::HostPoweredOff: {
+ bool success = false;
+ if (d_ptr->adapter()) {
+ if (QtAndroidPrivate::androidSdkVersion() >= 31) {
+ success = (bool)QAndroidJniObject::callStaticMethod<jboolean>(
+ "org/qtproject/qt5/android/bluetooth/QtBluetoothBroadcastReceiver",
+ "setDisabled");
+ } else {
+ success = (bool)d_ptr->adapter()->callMethod<jboolean>("disable", "()Z");
+ }
+ }
+ if (!success) {
+ qCWarning(QT_BT_ANDROID) << "Unable to power off the adapter";
emit error(QBluetoothLocalDevice::UnknownError);
- } else if (mode == QBluetoothLocalDevice::HostConnectable) {
- if (hostMode() == QBluetoothLocalDevice::HostDiscoverable) {
- // cannot directly go from Discoverable to Connectable
- // we need to go to disabled mode and enable once disabling came through
+ }
+ break;
+ }
+ case QBluetoothLocalDevice::HostConnectable: {
+ if (hostMode() == QBluetoothLocalDevice::HostDiscoverable) {
+ // On Android 'Discoverable' is actually 'CONNECTABLE_DISCOVERABLE', and
+ // it seems we cannot go directly from "Discoverable" to "Connectable". Instead
+ // we need to go to disabled mode first and then to the 'Connectable' mode
setHostMode(QBluetoothLocalDevice::HostPoweredOff);
- d_ptr->pendingHostModeTransition = true;
+ d_ptr->pendingConnectableHostModeTransition = true;
} else {
- QAndroidJniObject::callStaticMethod<void>(
- "org/qtproject/qt5/android/bluetooth/QtBluetoothBroadcastReceiver",
- "setConnectable");
+ const bool success = (bool)QAndroidJniObject::callStaticMethod<jboolean>(
+ "org/qtproject/qt5/android/bluetooth/QtBluetoothBroadcastReceiver",
+ "setEnabled");
+ if (!success) {
+ qCWarning(QT_BT_ANDROID) << "Unable to enable the Bluetooth";
+ emit error(QBluetoothLocalDevice::UnknownError);
+ }
+ }
+ break;
+ }
+
+ case QBluetoothLocalDevice::HostDiscoverable: {
+ if (!ensureAndroidPermission(BluetoothPermission::Advertise)) {
+ qCWarning(QT_BT_ANDROID) << "Local device setHostMode() failed due to"
+ "missing permissions";
+ return;
+ }
+ const bool success = (bool)QAndroidJniObject::callStaticMethod<jboolean>(
+ "org/qtproject/qt5/android/bluetooth/QtBluetoothBroadcastReceiver",
+ "setDiscoverable");
+ if (!success) {
+ qCWarning(QT_BT_ANDROID) << "Unable to set Bluetooth as discoverable";
+ emit error(QBluetoothLocalDevice::UnknownError);
}
- } else if (mode == QBluetoothLocalDevice::HostDiscoverable
- || mode == QBluetoothLocalDevice::HostDiscoverableLimitedInquiry) {
- QAndroidJniObject::callStaticMethod<void>(
- "org/qtproject/qt5/android/bluetooth/QtBluetoothBroadcastReceiver", "setDiscoverable");
+ break;
+ }
+ default:
+ qCWarning(QT_BT_ANDROID) << "setHostMode() unsupported host mode:" << nextMode;
+ break;
}
}
@@ -308,6 +364,12 @@ QBluetoothLocalDevice::HostMode QBluetoothLocalDevice::hostMode() const
QList<QBluetoothHostInfo> QBluetoothLocalDevice::allDevices()
{
+ // As a static class function we need to ensure permissions here (in addition to initialize())
+ if (!ensureAndroidPermission(BluetoothPermission::Connect)) {
+ qCWarning(QT_BT_ANDROID) << "Local device allDevices() failed due to"
+ "missing permissions";
+ return {};
+ }
// Android only supports max of one device (so far)
QList<QBluetoothHostInfo> localDevices;
diff --git a/src/bluetooth/qbluetoothlocaldevice_p.h b/src/bluetooth/qbluetoothlocaldevice_p.h
index 0c88f691..6bb74737 100644
--- a/src/bluetooth/qbluetoothlocaldevice_p.h
+++ b/src/bluetooth/qbluetoothlocaldevice_p.h
@@ -138,7 +138,7 @@ private:
public:
LocalDeviceBroadcastReceiver *receiver;
- bool pendingHostModeTransition = false;
+ bool pendingConnectableHostModeTransition = false;
QList<QPair<QBluetoothAddress, bool> > pendingPairings;
QList<QBluetoothAddress> connectedDevices;
diff --git a/src/bluetooth/qbluetoothserver_android.cpp b/src/bluetooth/qbluetoothserver_android.cpp
index eed3a1ea..d75d22b9 100644
--- a/src/bluetooth/qbluetoothserver_android.cpp
+++ b/src/bluetooth/qbluetoothserver_android.cpp
@@ -37,15 +37,16 @@
**
****************************************************************************/
-#include <QtCore/QLoggingCategory>
+#include "android/serveracceptancethread_p.h"
+#include "android/androidutils_p.h"
#include "qbluetoothserver.h"
#include "qbluetoothserver_p.h"
#include "qbluetoothsocket.h"
#include "qbluetoothsocket_android_p.h"
#include "qbluetoothlocaldevice.h"
-#include "android/serveracceptancethread_p.h"
#include <QCoreApplication>
+#include <QtCore/QLoggingCategory>
QT_BEGIN_NAMESPACE
@@ -133,6 +134,13 @@ bool QBluetoothServer::listen(const QBluetoothAddress &localAdapter, quint16 por
return false;
}
+ if (!ensureAndroidPermission(BluetoothPermission::Connect)) {
+ qCWarning(QT_BT_ANDROID) << "Bluetooth server listen() failed due to missing permissions";
+ d->m_lastError = QBluetoothServer::UnknownError;
+ emit error(d->m_lastError);
+ return false;
+ }
+
const QList<QBluetoothHostInfo> localDevices = QBluetoothLocalDevice::allDevices();
if (!localDevices.count()) {
qCWarning(QT_BT_ANDROID) << "Device does not support Bluetooth";
diff --git a/src/bluetooth/qbluetoothservicediscoveryagent_android.cpp b/src/bluetooth/qbluetoothservicediscoveryagent_android.cpp
index 96da5ddc..5aab9b4c 100644
--- a/src/bluetooth/qbluetoothservicediscoveryagent_android.cpp
+++ b/src/bluetooth/qbluetoothservicediscoveryagent_android.cpp
@@ -37,6 +37,13 @@
**
****************************************************************************/
+
+#include "qbluetoothservicediscoveryagent_p.h"
+#include "qbluetoothsocket_android_p.h"
+#include "android/servicediscoverybroadcastreceiver_p.h"
+#include "android/localdevicebroadcastreceiver_p.h"
+#include "android/androidutils_p.h"
+
#include <QtCore/qcoreapplication.h>
#include <QtCore/QLoggingCategory>
#include <QtCore/QTimer>
@@ -46,11 +53,6 @@
#include <QtBluetooth/QBluetoothLocalDevice>
#include <QtBluetooth/QBluetoothServiceDiscoveryAgent>
-#include "qbluetoothservicediscoveryagent_p.h"
-#include "qbluetoothsocket_android_p.h"
-#include "android/servicediscoverybroadcastreceiver_p.h"
-#include "android/localdevicebroadcastreceiver_p.h"
-
QT_BEGIN_NAMESPACE
Q_DECLARE_LOGGING_CATEGORY(QT_BT_ANDROID)
@@ -123,6 +125,15 @@ void QBluetoothServiceDiscoveryAgentPrivate::start(const QBluetoothAddress &addr
{
Q_Q(QBluetoothServiceDiscoveryAgent);
+ if (!ensureAndroidPermission(BluetoothPermission::Connect)) {
+ qCWarning(QT_BT_ANDROID) << "Service discovery start() failed due to missing permissions";
+ error = QBluetoothServiceDiscoveryAgent::UnknownError;
+ errorString = QBluetoothServiceDiscoveryAgent::tr("Unable to perform SDP scan");
+ emit q->error(error);
+ _q_serviceDiscoveryFinished();
+ return;
+ }
+
if (!btAdapter.isValid()) {
if (m_deviceAdapterAddress.isNull()) {
error = QBluetoothServiceDiscoveryAgent::UnknownError;
@@ -252,9 +263,11 @@ void QBluetoothServiceDiscoveryAgentPrivate::stop()
discoveredDevices.clear();
//kill receiver to limit load of signals
- receiver->unregisterReceiver();
- receiver->deleteLater();
- receiver = nullptr;
+ if (receiver) {
+ receiver->unregisterReceiver();
+ receiver->deleteLater();
+ receiver = nullptr;
+ }
Q_Q(QBluetoothServiceDiscoveryAgent);
emit q->canceled();
@@ -469,8 +482,11 @@ void QBluetoothServiceDiscoveryAgentPrivate::populateDiscoveredServices(const QB
//don't include the service if we already discovered it before
if (!isDuplicatedService(serviceInfo)) {
discoveredServices << serviceInfo;
- //qCDebug(QT_BT_ANDROID) << serviceInfo;
- emit q->serviceDiscovered(serviceInfo);
+ // Use queued connection to allow us finish the service discovery reporting;
+ // the application might call stop() when it has detected the service-of-interest,
+ // which in turn can cause the use of already released resources
+ QMetaObject::invokeMethod(q, "serviceDiscovered", Qt::QueuedConnection,
+ Q_ARG(QBluetoothServiceInfo, serviceInfo));
}
}
}
@@ -490,9 +506,11 @@ void QBluetoothServiceDiscoveryAgentPrivate::_q_fetchUuidsTimeout()
Q_ASSERT(sdpCache.isEmpty());
//kill receiver to limit load of signals
- receiver->unregisterReceiver();
- receiver->deleteLater();
- receiver = nullptr;
+ if (receiver) {
+ receiver->unregisterReceiver();
+ receiver->deleteLater();
+ receiver = nullptr;
+ }
_q_serviceDiscoveryFinished();
}
@@ -507,9 +525,11 @@ void QBluetoothServiceDiscoveryAgentPrivate::_q_hostModeStateChanged(QBluetoothL
errorString = QBluetoothServiceDiscoveryAgent::tr("Device is powered off");
//kill receiver to limit load of signals
- receiver->unregisterReceiver();
- receiver->deleteLater();
- receiver = nullptr;
+ if (receiver) {
+ receiver->unregisterReceiver();
+ receiver->deleteLater();
+ receiver = nullptr;
+ }
Q_Q(QBluetoothServiceDiscoveryAgent);
emit q->error(error);
diff --git a/src/bluetooth/qbluetoothservicediscoveryagent_p.cpp b/src/bluetooth/qbluetoothservicediscoveryagent_p.cpp
index a23fda95..39f30e3f 100644
--- a/src/bluetooth/qbluetoothservicediscoveryagent_p.cpp
+++ b/src/bluetooth/qbluetoothservicediscoveryagent_p.cpp
@@ -73,3 +73,5 @@ void QBluetoothServiceDiscoveryAgentPrivate::stop()
}
QT_END_NAMESPACE
+
+#include "moc_qbluetoothservicediscoveryagent_p.cpp"
diff --git a/src/bluetooth/qbluetoothserviceinfo_android.cpp b/src/bluetooth/qbluetoothserviceinfo_android.cpp
index b0193f73..348a40c5 100644
--- a/src/bluetooth/qbluetoothserviceinfo_android.cpp
+++ b/src/bluetooth/qbluetoothserviceinfo_android.cpp
@@ -37,8 +37,8 @@
**
****************************************************************************/
-#include <QtCore/QLoggingCategory>
+#include "android/androidutils_p.h"
#include "qbluetoothhostinfo.h"
#include "qbluetoothlocaldevice.h"
#include "qbluetoothserviceinfo.h"
@@ -46,6 +46,8 @@
#include "qbluetoothserver_p.h"
#include "qbluetoothserver.h"
+#include <QtCore/QLoggingCategory>
+
QT_BEGIN_NAMESPACE
Q_DECLARE_LOGGING_CATEGORY(QT_BT_ANDROID)
@@ -89,6 +91,12 @@ bool QBluetoothServiceInfoPrivate::unregisterService()
bool QBluetoothServiceInfoPrivate::registerService(const QBluetoothAddress& localAdapter)
{
+ if (!ensureAndroidPermission(BluetoothPermission::Connect)) {
+ qCWarning(QT_BT_ANDROID) << "Serviceinfo registerService() failed due to"
+ "missing permissions";
+ return false;
+ }
+
const QList<QBluetoothHostInfo> localDevices = QBluetoothLocalDevice::allDevices();
if (!localDevices.count())
return false; //no Bluetooth device
diff --git a/src/bluetooth/qbluetoothserviceinfo_p.cpp b/src/bluetooth/qbluetoothserviceinfo_p.cpp
index 43e08db5..2f19a399 100644
--- a/src/bluetooth/qbluetoothserviceinfo_p.cpp
+++ b/src/bluetooth/qbluetoothserviceinfo_p.cpp
@@ -73,3 +73,5 @@ bool QBluetoothServiceInfoPrivate::unregisterService()
}
QT_END_NAMESPACE
+
+#include "moc_qbluetoothserviceinfo_p.cpp"
diff --git a/src/bluetooth/qbluetoothsocket_android.cpp b/src/bluetooth/qbluetoothsocket_android.cpp
index 85da325b..b07a1f81 100644
--- a/src/bluetooth/qbluetoothsocket_android.cpp
+++ b/src/bluetooth/qbluetoothsocket_android.cpp
@@ -43,6 +43,7 @@
#include "qbluetoothaddress.h"
#include "qbluetoothdeviceinfo.h"
#include "qbluetoothserviceinfo.h"
+#include "android/androidutils_p.h"
#include <QtCore/QLoggingCategory>
#include <QtCore/QThread>
#include <QtCore/QTime>
@@ -407,7 +408,15 @@ void QBluetoothSocketPrivateAndroid::connectToServiceHelper(const QBluetoothAddr
qCDebug(QT_BT_ANDROID) << "connectToServiceHelper()" << address.toString() << uuid.toString();
- q->setSocketState(QBluetoothSocket::ConnectingState);
+ if (!ensureAndroidPermission(BluetoothPermission::Connect)) {
+ qCWarning(QT_BT_ANDROID) << "Bluetooth socket connect failed due to missing permissions";
+ errorString = QBluetoothSocket::tr("Unknown socket error");
+ q->setSocketError(QBluetoothSocket::SocketError::UnknownSocketError);
+ q->setSocketState(QBluetoothSocket::SocketState::UnconnectedState);
+ return;
+ }
+
+ q->setSocketState(QBluetoothSocket::SocketState::ConnectingState);
if (!adapter.isValid()) {
qCWarning(QT_BT_ANDROID) << "Device does not support Bluetooth";
@@ -419,7 +428,7 @@ void QBluetoothSocketPrivateAndroid::connectToServiceHelper(const QBluetoothAddr
const int state = adapter.callMethod<jint>("getState");
if (state != 12 ) { //BluetoothAdapter.STATE_ON
- qCWarning(QT_BT_ANDROID) << "Bt device offline";
+ qCWarning(QT_BT_ANDROID) << "Bluetooth device offline";
errorString = QBluetoothSocket::tr("Device is powered off");
q->setSocketError(QBluetoothSocket::NetworkError);
q->setSocketState(QBluetoothSocket::UnconnectedState);
@@ -457,7 +466,7 @@ void QBluetoothSocketPrivateAndroid::connectToServiceHelper(const QBluetoothAddr
"(Ljava/util/UUID;)Landroid/bluetooth/BluetoothSocket;",
uuidObject.object<jobject>());
} else {
- qCDebug(QT_BT_ANDROID) << "Connnecting via secure rfcomm";
+ qCDebug(QT_BT_ANDROID) << "Connecting via secure rfcomm";
socketObject = remoteDevice.callObjectMethod("createRfcommSocketToServiceRecord",
"(Ljava/util/UUID;)Landroid/bluetooth/BluetoothSocket;",
uuidObject.object<jobject>());
@@ -724,8 +733,12 @@ void QBluetoothSocketPrivateAndroid::abort()
QString QBluetoothSocketPrivateAndroid::localName() const
{
- if (adapter.isValid())
+ if (!ensureAndroidPermission(BluetoothPermission::Connect)) {
+ qCWarning(QT_BT_ANDROID) << "Bluetooth socket localName() failed due to"
+ "missing permissions";
+ } else if (adapter.isValid()) {
return adapter.callObjectMethod<jstring>("getName").toString();
+ }
return QString();
}
@@ -733,8 +746,13 @@ QString QBluetoothSocketPrivateAndroid::localName() const
QBluetoothAddress QBluetoothSocketPrivateAndroid::localAddress() const
{
QString result;
- if (adapter.isValid())
+
+ if (!ensureAndroidPermission(BluetoothPermission::Connect)) {
+ qCWarning(QT_BT_ANDROID) << "Bluetooth socket localAddress() failed due to"
+ "missing permissions";
+ } else if (adapter.isValid()) {
result = adapter.callObjectMethod("getAddress", "()Ljava/lang/String;").toString();
+ }
return QBluetoothAddress(result);
}
diff --git a/src/bluetooth/qbluetoothsocket_bluez.cpp b/src/bluetooth/qbluetoothsocket_bluez.cpp
index 2c22fde6..da92082d 100644
--- a/src/bluetooth/qbluetoothsocket_bluez.cpp
+++ b/src/bluetooth/qbluetoothsocket_bluez.cpp
@@ -711,3 +711,5 @@ bool QBluetoothSocketPrivateBluez::canReadLine() const
}
QT_END_NAMESPACE
+
+#include "moc_qbluetoothsocket_bluez_p.cpp"
diff --git a/src/bluetooth/qbluetoothsocket_bluezdbus.cpp b/src/bluetooth/qbluetoothsocket_bluezdbus.cpp
index d6aa17a7..54ff9b7e 100644
--- a/src/bluetooth/qbluetoothsocket_bluezdbus.cpp
+++ b/src/bluetooth/qbluetoothsocket_bluezdbus.cpp
@@ -627,3 +627,5 @@ void QBluetoothSocketPrivateBluezDBus::clearSocket()
profilePath.clear();
}
QT_END_NAMESPACE
+
+#include "moc_qbluetoothsocket_bluezdbus_p.cpp"
diff --git a/src/bluetooth/qbluetoothsocket_osx.mm b/src/bluetooth/qbluetoothsocket_osx.mm
index dcb9aa03..e3f124ab 100644
--- a/src/bluetooth/qbluetoothsocket_osx.mm
+++ b/src/bluetooth/qbluetoothsocket_osx.mm
@@ -393,7 +393,6 @@ void QBluetoothSocketPrivate::connectToService(const QBluetoothAddress &address,
// Connected, setOpenMode on a QBluetoothSocket.
q_ptr->setOpenMode(openMode);
q_ptr->setSocketState(QBluetoothSocket::ConnectedState);
- emit q_ptr->connected();
if (buffer.size()) // We also have some data already ...
emit q_ptr->readyRead();
} else if (state == QBluetoothSocket::UnconnectedState) {
@@ -521,7 +520,6 @@ void QBluetoothSocketPrivate::channelOpenComplete()
if (!isConnecting) {
q_ptr->setOpenMode(openMode);
q_ptr->setSocketState(QBluetoothSocket::ConnectedState);
- emit q_ptr->connected();
} else {
state = QBluetoothSocket::ConnectedState;
// We are still in connectToService, it'll care
diff --git a/src/bluetooth/qbluetoothsocketbase.cpp b/src/bluetooth/qbluetoothsocketbase.cpp
index 8401a1c3..0276a5ce 100644
--- a/src/bluetooth/qbluetoothsocketbase.cpp
+++ b/src/bluetooth/qbluetoothsocketbase.cpp
@@ -52,3 +52,5 @@ QBluetoothSocketBasePrivate::~QBluetoothSocketBasePrivate()
}
QT_END_NAMESPACE
+
+#include "moc_qbluetoothsocketbase_p.cpp"
diff --git a/src/bluetooth/qleadvertiser_bluez.cpp b/src/bluetooth/qleadvertiser_bluez.cpp
index 47daed25..46afebe5 100644
--- a/src/bluetooth/qleadvertiser_bluez.cpp
+++ b/src/bluetooth/qleadvertiser_bluez.cpp
@@ -37,7 +37,7 @@
**
****************************************************************************/
-#include "qleadvertiser_p.h"
+#include "qleadvertiser_bluez_p.h"
#include "bluez/bluez_data_p.h"
#include "bluez/hcimanager_p.h"
@@ -460,3 +460,5 @@ void QLeAdvertiserBluez::handleError()
}
QT_END_NAMESPACE
+
+#include "moc_qleadvertiser_bluez_p.cpp"
diff --git a/src/bluetooth/qleadvertiser_p.h b/src/bluetooth/qleadvertiser_bluez_p.h
index 9b8ffbb5..8102be28 100644
--- a/src/bluetooth/qleadvertiser_p.h
+++ b/src/bluetooth/qleadvertiser_bluez_p.h
@@ -37,8 +37,8 @@
**
****************************************************************************/
-#ifndef QLEADVERTISER_P_H
-#define QLEADVERTISER_P_H
+#ifndef QLEADVERTISER_BLUEZ_P_H
+#define QLEADVERTISER_BLUEZ_P_H
//
// W A R N I N G
@@ -54,9 +54,9 @@
#include "qlowenergyadvertisingdata.h"
#include "qlowenergyadvertisingparameters.h"
-#if QT_CONFIG(bluez)
+QT_REQUIRE_CONFIG(bluez);
+
#include "bluez/bluez_data_p.h"
-#endif
#include <QtCore/qobject.h>
#include <QtCore/qvector.h>
@@ -94,14 +94,13 @@ private:
const QLowEnergyAdvertisingData m_responseData;
};
-
-#if QT_CONFIG(bluez)
struct AdvData;
struct AdvParams;
class HciManager;
class QLeAdvertiserBluez : public QLeAdvertiser
{
+ Q_OBJECT
public:
QLeAdvertiserBluez(const QLowEnergyAdvertisingParameters &params,
const QLowEnergyAdvertisingData &advertisingData,
@@ -147,7 +146,6 @@ private:
quint8 m_powerLevel;
bool m_sendPowerLevel;
};
-#endif // QT_CONFIG(bluez)
QT_END_NAMESPACE
diff --git a/src/bluetooth/qlowenergyadvertisingdata.h b/src/bluetooth/qlowenergyadvertisingdata.h
index 0fc55adb..26006f27 100644
--- a/src/bluetooth/qlowenergyadvertisingdata.h
+++ b/src/bluetooth/qlowenergyadvertisingdata.h
@@ -84,7 +84,7 @@ public:
void setRawData(const QByteArray &data);
QByteArray rawData() const;
- void swap(QLowEnergyAdvertisingData &other) Q_DECL_NOTHROW { qSwap(d, other.d); }
+ void swap(QLowEnergyAdvertisingData &other) noexcept { d.swap(other.d); }
private:
QSharedDataPointer<QLowEnergyAdvertisingDataPrivate> d;
diff --git a/src/bluetooth/qlowenergyadvertisingparameters.h b/src/bluetooth/qlowenergyadvertisingparameters.h
index 055026e6..c834cf76 100644
--- a/src/bluetooth/qlowenergyadvertisingparameters.h
+++ b/src/bluetooth/qlowenergyadvertisingparameters.h
@@ -90,7 +90,7 @@ public:
// TODO: own address type
// TODO: For ADV_DIRECT_IND: peer address + peer address type
- void swap(QLowEnergyAdvertisingParameters &other) Q_DECL_NOTHROW { qSwap(d, other.d); }
+ void swap(QLowEnergyAdvertisingParameters &other) noexcept { d.swap(other.d); }
private:
QSharedDataPointer<QLowEnergyAdvertisingParametersPrivate> d;
diff --git a/src/bluetooth/qlowenergycharacteristicdata.h b/src/bluetooth/qlowenergycharacteristicdata.h
index cf5de703..276a196f 100644
--- a/src/bluetooth/qlowenergycharacteristicdata.h
+++ b/src/bluetooth/qlowenergycharacteristicdata.h
@@ -82,7 +82,7 @@ public:
bool isValid() const;
- void swap(QLowEnergyCharacteristicData &other) Q_DECL_NOTHROW { qSwap(d, other.d); }
+ void swap(QLowEnergyCharacteristicData &other) noexcept { d.swap(other.d); }
private:
QSharedDataPointer<QLowEnergyCharacteristicDataPrivate> d;
diff --git a/src/bluetooth/qlowenergyconnectionparameters.h b/src/bluetooth/qlowenergyconnectionparameters.h
index c765763f..2e4950d8 100644
--- a/src/bluetooth/qlowenergyconnectionparameters.h
+++ b/src/bluetooth/qlowenergyconnectionparameters.h
@@ -69,7 +69,7 @@ public:
void setSupervisionTimeout(int timeout);
int supervisionTimeout() const;
- void swap(QLowEnergyConnectionParameters &other) Q_DECL_NOTHROW { qSwap(d, other.d); }
+ void swap(QLowEnergyConnectionParameters &other) noexcept { d.swap(other.d); }
private:
QSharedDataPointer<QLowEnergyConnectionParametersPrivate> d;
diff --git a/src/bluetooth/qlowenergycontroller.cpp b/src/bluetooth/qlowenergycontroller.cpp
index 06fa0369..b065555c 100644
--- a/src/bluetooth/qlowenergycontroller.cpp
+++ b/src/bluetooth/qlowenergycontroller.cpp
@@ -54,6 +54,7 @@
#include "qlowenergycontroller_bluez_p.h"
#elif defined(QT_ANDROID_BLUETOOTH)
#include "qlowenergycontroller_android_p.h"
+#include "android/androidutils_p.h"
#elif defined(QT_WINRT_BLUETOOTH)
#include "qtbluetoothglobal_p.h"
#include "qlowenergycontroller_winrt_p.h"
@@ -74,6 +75,9 @@ QT_BEGIN_NAMESPACE
Q_DECLARE_LOGGING_CATEGORY(QT_BT)
Q_DECLARE_LOGGING_CATEGORY(QT_BT_WINRT)
+#if defined(QT_ANDROID_BLUETOOTH)
+Q_DECLARE_LOGGING_CATEGORY(QT_BT_ANDROID)
+#endif
/*!
\class QLowEnergyController
@@ -212,7 +216,7 @@ Q_DECLARE_LOGGING_CATEGORY(QT_BT_WINRT)
\sa QLowEnergyController::createCentral()
\sa QLowEnergyController::createPeripheral()
\since 5.7
- \note The peripheral role is currently only supported on Linux. In addition, handling the
+ \note The peripheral role is not supported on Windows. In addition on Linux, handling the
"Signed Write" ATT command on the server side requires BlueZ 5 and kernel version 3.7
or newer.
*/
@@ -635,6 +639,7 @@ void QLowEnergyController::connectToDevice()
}
if (!d->isValidLocalAdapter()) {
+ qCWarning(QT_BT) << "connectToDevice() LE controller has invalid adapter";
d->setError(QLowEnergyController::InvalidBluetoothAdapterError);
return;
}
@@ -842,6 +847,13 @@ QLowEnergyService *QLowEnergyController::addService(const QLowEnergyServiceData
return nullptr;
}
+#if defined(QT_ANDROID_BLUETOOTH)
+ if (!ensureAndroidPermission(BluetoothPermission::Connect)) {
+ qCWarning(QT_BT_ANDROID) << "addService() failed due to missing permissions";
+ return nullptr;
+ }
+#endif
+
Q_D(QLowEnergyController);
QLowEnergyService *newService = d->addServiceHelper(service);
if (newService)
@@ -916,3 +928,5 @@ QLowEnergyController::Role QLowEnergyController::role() const
}
QT_END_NAMESPACE
+
+#include "moc_qlowenergycontroller.cpp"
diff --git a/src/bluetooth/qlowenergycontroller_android.cpp b/src/bluetooth/qlowenergycontroller_android.cpp
index e0f3eef7..656c5a22 100644
--- a/src/bluetooth/qlowenergycontroller_android.cpp
+++ b/src/bluetooth/qlowenergycontroller_android.cpp
@@ -37,6 +37,7 @@
**
****************************************************************************/
+#include "android/androidutils_p.h"
#include "qlowenergycontroller_android_p.h"
#include <QtCore/QLoggingCategory>
#include <QtAndroidExtras/QAndroidJniEnvironment>
@@ -144,8 +145,17 @@ void QLowEnergyControllerPrivateAndroid::init()
void QLowEnergyControllerPrivateAndroid::connectToDevice()
{
- if (!hub)
- return; // Android version below v18
+ if (!hub) {
+ qCCritical(QT_BT_ANDROID) << "connectToDevice() LE controller has not been initialized";
+ return;
+ }
+
+ if (!ensureAndroidPermission(BluetoothPermission::Connect)) {
+ // This is unlikely to happen as a valid local adapter is a precondition
+ setError(QLowEnergyController::AuthorizationError);
+ qCWarning(QT_BT_ANDROID) << "connectToDevice() failed due to missing permissions";
+ return;
+ }
// required to pass unit test on default backend
if (remoteDevice.isNull()) {
@@ -195,6 +205,8 @@ void QLowEnergyControllerPrivateAndroid::disconnectFromDevice()
void QLowEnergyControllerPrivateAndroid::discoverServices()
{
+ // No need to check bluetooth permissions here as 'connected' is a precondition
+
if (hub && hub->javaObject().callMethod<jboolean>("discoverServices")) {
qCDebug(QT_BT_ANDROID) << "Service discovery initiated";
} else {
@@ -1013,7 +1025,15 @@ void QLowEnergyControllerPrivateAndroid::startAdvertising(const QLowEnergyAdvert
{
setState(QLowEnergyController::AdvertisingState);
- if (!hub->javaObject().isValid()) {
+ if (!(ensureAndroidPermission(BluetoothPermission::Advertise) &&
+ ensureAndroidPermission(BluetoothPermission::Connect))) {
+ qCWarning(QT_BT_ANDROID) << "startAdvertising() failed due to missing permissions";
+ setError(QLowEnergyController::AdvertisingError);
+ setState(QLowEnergyController::UnconnectedState);
+ return;
+ }
+
+ if (!hub || !hub->javaObject().isValid()) {
qCWarning(QT_BT_ANDROID) << "Cannot initiate QtBluetoothLEServer";
setError(QLowEnergyController::AdvertisingError);
setState(QLowEnergyController::UnconnectedState);
diff --git a/src/bluetooth/qlowenergycontroller_android_p.h b/src/bluetooth/qlowenergycontroller_android_p.h
index f05c63ca..9139d267 100644
--- a/src/bluetooth/qlowenergycontroller_android_p.h
+++ b/src/bluetooth/qlowenergycontroller_android_p.h
@@ -74,8 +74,6 @@ class LowEnergyNotificationHub;
extern void registerQLowEnergyControllerMetaType();
-class QLeAdvertiser;
-
class QLowEnergyControllerPrivateAndroid final : public QLowEnergyControllerPrivate
{
Q_OBJECT
diff --git a/src/bluetooth/qlowenergycontroller_bluez.cpp b/src/bluetooth/qlowenergycontroller_bluez.cpp
index dfa21004..6cb6ad66 100644
--- a/src/bluetooth/qlowenergycontroller_bluez.cpp
+++ b/src/bluetooth/qlowenergycontroller_bluez.cpp
@@ -42,7 +42,7 @@
#include "qlowenergycontroller_bluez_p.h"
#include "qbluetoothsocketbase_p.h"
#include "qbluetoothsocket_bluez_p.h"
-#include "qleadvertiser_p.h"
+#include "qleadvertiser_bluez_p.h"
#include "bluez/bluez_data_p.h"
#include "bluez/hcimanager_p.h"
#include "bluez/objectmanager_p.h"
@@ -3543,3 +3543,5 @@ bool QLowEnergyControllerPrivateBluez::verifyMac(const QByteArray &message, cons
}
QT_END_NAMESPACE
+
+#include "moc_qlowenergycontroller_bluez_p.cpp"
diff --git a/src/bluetooth/qlowenergycontroller_bluezdbus.cpp b/src/bluetooth/qlowenergycontroller_bluezdbus.cpp
index c159e97e..2dbb28ae 100644
--- a/src/bluetooth/qlowenergycontroller_bluezdbus.cpp
+++ b/src/bluetooth/qlowenergycontroller_bluezdbus.cpp
@@ -415,7 +415,8 @@ void QLowEnergyControllerPrivateBluezDBus::discoverServices()
Q_Q(QLowEnergyController);
auto setupServicePrivate = [&, q](
- QLowEnergyService::ServiceType type, const QBluetoothUuid &uuid, const QString &path){
+ QLowEnergyService::ServiceType type, const QBluetoothUuid &uuid,
+ const QString &path, const bool battery1Interface = false){
QSharedPointer<QLowEnergyServicePrivate> priv = QSharedPointer<QLowEnergyServicePrivate>::create();
priv->uuid = uuid;
priv->type = type; // we make a guess we cannot validate
@@ -423,8 +424,11 @@ void QLowEnergyControllerPrivateBluezDBus::discoverServices()
GattService serviceContainer;
serviceContainer.servicePath = path;
- if (uuid == QBluetoothUuid::BatteryService)
+
+ if (battery1Interface) {
+ qCDebug(QT_BT_BLUEZ) << "Using Battery1 interface to emulate generic interface";
serviceContainer.hasBatteryService = true;
+ }
serviceList.insert(priv->uuid, priv);
dbusServices.insert(priv->uuid, serviceContainer);
@@ -434,25 +438,50 @@ void QLowEnergyControllerPrivateBluezDBus::discoverServices()
const ManagedObjectList managedObjectList = reply.value();
const QString servicePathPrefix = device->path().append(QStringLiteral("/service"));
+
+ // The Bluez battery service (0x180f) support has evolved over time and needs additional logic:
+ //
+ // * Until 5.47 Bluez exposes battery services via generic interface (GattService1) only
+ // * Between 5.48..5.54 Bluez exposes battery service as a dedicated 'Battery1' interface only
+ // * From 5.55 Bluez exposes both the generic service as well as the dedicated 'Battery1'
+ //
+ // To hide the difference from users the 'Battery1' interface will be used to emulate the
+ // generic interface. Importantly also the GattService1 interface, if available, is available
+ // early whereas the Battery1 interface may be available only later (generated too late for
+ // this service discovery's purposes)
+ //
+ // The precedence for battery service here is as follows:
+ // * If available via GattService1, use that and ignore possible Battery1 interface
+ // * If Battery1 interface is available or the 'org.bluez.Device1' lists battery service
+ // amongst list of available services, mark the service such that the code will later
+ // look up the Battery1 service details
+ bool gattBatteryService{false};
+ QString batteryServicePath;
+
for (ManagedObjectList::const_iterator it = managedObjectList.constBegin(); it != managedObjectList.constEnd(); ++it) {
const InterfaceList &ifaceList = it.value();
if (!it.key().path().startsWith(device->path()))
continue;
- // Since Bluez 5.48 battery services (0x180f) are no longer exposed
- // as generic services under servicePathPrefix.
- // A dedicated org.bluez.Battery1 interface is exposed. Here we are going to revert
- // Bettery1 to the generic pattern.
if (it.key().path() == device->path()) {
- // find Battery1 service
+ // See if the battery service is available or is assumed to be available later
for (InterfaceList::const_iterator battIter = ifaceList.constBegin(); battIter != ifaceList.constEnd(); ++battIter) {
const QString &iface = battIter.key();
if (iface == QStringLiteral("org.bluez.Battery1")) {
- qCDebug(QT_BT_BLUEZ) << "Found dedicated Battery service -> emulating generic btle access";
- setupServicePrivate(QLowEnergyService::PrimaryService,
- QBluetoothUuid::BatteryService,
- it.key().path());
+ qCDebug(QT_BT_BLUEZ) << "Dedicated Battery1 service available";
+ batteryServicePath = it.key().path();
+ break;
+ } else if (iface == QStringLiteral("org.bluez.Device1")) {
+ for (auto const& uuid :
+ battIter.value()[QStringLiteral("UUIDs")].toStringList()) {
+ if (QBluetoothUuid(uuid) ==
+ QBluetoothUuid::ServiceClassUuid::BatteryService) {
+ qCDebug(QT_BT_BLUEZ) << "Battery service listed as available service";
+ batteryServicePath = it.key().path();
+ break;
+ }
+ }
}
}
continue;
@@ -468,6 +497,11 @@ void QLowEnergyControllerPrivateBluezDBus::discoverServices()
QScopedPointer<OrgBluezGattService1Interface> service(new OrgBluezGattService1Interface(
QStringLiteral("org.bluez"),it.key().path(),
QDBusConnection::systemBus(), this));
+ if (QBluetoothUuid(service->uUID()) ==
+ QBluetoothUuid::ServiceClassUuid::BatteryService) {
+ qCDebug(QT_BT_BLUEZ) << "Using battery service via GattService1 interface";
+ gattBatteryService = true;
+ }
setupServicePrivate(service->primary()
? QLowEnergyService::PrimaryService
: QLowEnergyService::IncludedService,
@@ -476,6 +510,12 @@ void QLowEnergyControllerPrivateBluezDBus::discoverServices()
}
}
+ if (!gattBatteryService && !batteryServicePath.isEmpty()) {
+ setupServicePrivate(QLowEnergyService::PrimaryService,
+ QBluetoothUuid::ServiceClassUuid::BatteryService,
+ batteryServicePath, true);
+ }
+
setState(QLowEnergyController::DiscoveredState);
emit q->discoveryFinished();
}
@@ -1305,3 +1345,5 @@ QLowEnergyService *QLowEnergyControllerPrivateBluezDBus::addServiceHelper(
}
QT_END_NAMESPACE
+
+#include "moc_qlowenergycontroller_bluezdbus_p.cpp"
diff --git a/src/bluetooth/qlowenergycontrollerbase.cpp b/src/bluetooth/qlowenergycontrollerbase.cpp
index d151f871..d9645db7 100644
--- a/src/bluetooth/qlowenergycontrollerbase.cpp
+++ b/src/bluetooth/qlowenergycontrollerbase.cpp
@@ -329,3 +329,5 @@ QLowEnergyService *QLowEnergyControllerPrivate::addServiceHelper(
}
QT_END_NAMESPACE
+
+#include "moc_qlowenergycontrollerbase_p.cpp"
diff --git a/src/bluetooth/qlowenergydescriptordata.h b/src/bluetooth/qlowenergydescriptordata.h
index 856acf53..b4df4ec0 100644
--- a/src/bluetooth/qlowenergydescriptordata.h
+++ b/src/bluetooth/qlowenergydescriptordata.h
@@ -80,7 +80,7 @@ public:
bool isWritable() const;
QBluetooth::AttAccessConstraints writeConstraints() const;
- void swap(QLowEnergyDescriptorData &other) Q_DECL_NOTHROW { qSwap(d, other.d); }
+ void swap(QLowEnergyDescriptorData &other) noexcept { d.swap(other.d); }
private:
QSharedDataPointer<QLowEnergyDescriptorDataPrivate> d;
diff --git a/src/bluetooth/qlowenergyservice.cpp b/src/bluetooth/qlowenergyservice.cpp
index 2e6d1f9b..249df455 100644
--- a/src/bluetooth/qlowenergyservice.cpp
+++ b/src/bluetooth/qlowenergyservice.cpp
@@ -836,3 +836,5 @@ void QLowEnergyService::writeDescriptor(const QLowEnergyDescriptor &descriptor,
}
QT_END_NAMESPACE
+
+#include "moc_qlowenergyservice.cpp"
diff --git a/src/bluetooth/qlowenergyservicedata.h b/src/bluetooth/qlowenergyservicedata.h
index 4d553267..10ad907e 100644
--- a/src/bluetooth/qlowenergyservicedata.h
+++ b/src/bluetooth/qlowenergyservicedata.h
@@ -78,7 +78,7 @@ public:
bool isValid() const;
- void swap(QLowEnergyServiceData &other) Q_DECL_NOTHROW { qSwap(d, other.d); }
+ void swap(QLowEnergyServiceData &other) noexcept { d.swap(other.d); }
private:
QSharedDataPointer<QLowEnergyServiceDataPrivate> d;
diff --git a/src/bluetooth/qlowenergyserviceprivate.cpp b/src/bluetooth/qlowenergyserviceprivate.cpp
index 0b8d8be0..7214081e 100644
--- a/src/bluetooth/qlowenergyserviceprivate.cpp
+++ b/src/bluetooth/qlowenergyserviceprivate.cpp
@@ -83,3 +83,5 @@ void QLowEnergyServicePrivate::setState(QLowEnergyService::ServiceState newState
}
QT_END_NAMESPACE
+
+#include "moc_qlowenergyserviceprivate_p.cpp"
diff --git a/src/nfc/qnearfieldmanager.cpp b/src/nfc/qnearfieldmanager.cpp
index 82a8bfbe..757c8c99 100644
--- a/src/nfc/qnearfieldmanager.cpp
+++ b/src/nfc/qnearfieldmanager.cpp
@@ -440,3 +440,7 @@ QNearFieldManager::TargetAccessModes QNearFieldManager::targetAccessModes() cons
}
QT_END_NAMESPACE
+
+#include "moc_qnearfieldmanager_p.cpp"
+
+#include "moc_qnearfieldmanager.cpp"
diff --git a/src/nfc/qnearfieldtarget.cpp b/src/nfc/qnearfieldtarget.cpp
index 850408fe..b0aca5ca 100644
--- a/src/nfc/qnearfieldtarget.cpp
+++ b/src/nfc/qnearfieldtarget.cpp
@@ -551,3 +551,5 @@ void QNearFieldTarget::reportError(QNearFieldTarget::Error error,
}
QT_END_NAMESPACE
+
+#include "moc_qnearfieldtarget.cpp"
diff --git a/tests/auto/qbluetoothservicediscoveryagent/tst_qbluetoothservicediscoveryagent.cpp b/tests/auto/qbluetoothservicediscoveryagent/tst_qbluetoothservicediscoveryagent.cpp
index 52a0c8bd..cd44d9d6 100644
--- a/tests/auto/qbluetoothservicediscoveryagent/tst_qbluetoothservicediscoveryagent.cpp
+++ b/tests/auto/qbluetoothservicediscoveryagent/tst_qbluetoothservicediscoveryagent.cpp
@@ -121,10 +121,8 @@ void tst_QBluetoothServiceDiscoveryAgent::initTestCase()
QSignalSpy finishedSpy(&discoveryAgent, SIGNAL(finished()));
QSignalSpy errorSpy(&discoveryAgent, SIGNAL(error(QBluetoothDeviceDiscoveryAgent::Error)));
QSignalSpy discoveredSpy(&discoveryAgent, SIGNAL(deviceDiscovered(QBluetoothDeviceInfo)));
- // connect(&discoveryAgent, SIGNAL(deviceDiscovered(QBluetoothDeviceInfo)),
- // this, SLOT(deviceDiscoveryDebug(QBluetoothDeviceInfo)));
- discoveryAgent.start();
+ discoveryAgent.start(QBluetoothDeviceDiscoveryAgent::ClassicMethod);
// Wait for up to MaxScanTime for the scan to finish
int scanTime = MaxScanTime;
@@ -132,7 +130,6 @@ void tst_QBluetoothServiceDiscoveryAgent::initTestCase()
QTest::qWait(1000);
scanTime -= 1000;
}
- // qDebug() << "Scan time left:" << scanTime;
// Expect finished signal with no error
QVERIFY(finishedSpy.count() == 1);
@@ -386,7 +383,7 @@ void tst_QBluetoothServiceDiscoveryAgent::tst_serviceDiscovery()
QFETCH(QBluetoothServiceDiscoveryAgent::Error, serviceDiscoveryError);
QBluetoothLocalDevice localDevice;
- qDebug() << "Scanning address" << deviceInfo.address().toString();
+ qDebug() << "Scanning address" << deviceInfo.address().toString() << deviceInfo.name();
QBluetoothServiceDiscoveryAgent discoveryAgent(localDevice.address());
bool setAddress = discoveryAgent.setRemoteAddress(deviceInfo.address());
@@ -405,10 +402,8 @@ void tst_QBluetoothServiceDiscoveryAgent::tst_serviceDiscovery()
QSignalSpy finishedSpy(&discoveryAgent, SIGNAL(finished()));
QSignalSpy errorSpy(&discoveryAgent, SIGNAL(error(QBluetoothServiceDiscoveryAgent::Error)));
QSignalSpy discoveredSpy(&discoveryAgent, SIGNAL(serviceDiscovered(QBluetoothServiceInfo)));
-// connect(&discoveryAgent, SIGNAL(serviceDiscovered(QBluetoothServiceInfo)),
-// this, SLOT(serviceDiscoveryDebug(QBluetoothServiceInfo)));
- connect(&discoveryAgent, SIGNAL(error(QBluetoothServiceDiscoveryAgent::Error)),
- this, SLOT(serviceError(QBluetoothServiceDiscoveryAgent::Error)));
+ connect(&discoveryAgent, SIGNAL(error(QBluetoothServiceDiscoveryAgent::Error)), this,
+ SLOT(serviceError(QBluetoothServiceDiscoveryAgent::Error)));
discoveryAgent.start(QBluetoothServiceDiscoveryAgent::FullDiscovery);
@@ -419,7 +414,7 @@ void tst_QBluetoothServiceDiscoveryAgent::tst_serviceDiscovery()
QVERIFY(discoveryAgent.isActive() || !finishedSpy.isEmpty());
// Wait for up to MaxScanTime for the scan to finish
- int scanTime = MaxScanTime;
+ int scanTime = 20000;
while (finishedSpy.count() == 0 && scanTime > 0) {
QTest::qWait(1000);
scanTime -= 1000;
@@ -434,7 +429,9 @@ void tst_QBluetoothServiceDiscoveryAgent::tst_serviceDiscovery()
QVERIFY(discoveryAgent.errorString() == QString());
// Expect finished signal with no error
- QVERIFY(finishedSpy.count() == 1);
+ if (scanTime)
+ QVERIFY(finishedSpy.count() == 1);
+
QVERIFY(errorSpy.isEmpty());
//if (discoveryAgent.discoveredServices().count() && expected_failures++ <2){