summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorQt Forward Merge Bot <qt_forward_merge_bot@qt-project.org>2019-02-09 03:01:23 +0100
committerQt Forward Merge Bot <qt_forward_merge_bot@qt-project.org>2019-02-09 03:01:23 +0100
commit8231e50c82c1cc2834c13263408fd4e38440c772 (patch)
treee312ae40ef0dcbbe9de133425dc78e652e743370
parent005cef90c6e06ef419dcec8f4619402677470301 (diff)
parent1606ccb76ba72990df652fbd7f01d709ae20b63c (diff)
Merge remote-tracking branch 'origin/5.12' into 5.13
-rw-r--r--src/bluetooth/doc/src/bluetooth-index.qdoc2
-rw-r--r--src/bluetooth/osx/osxbtcentralmanager.mm4
-rw-r--r--src/bluetooth/osx/osxbtledeviceinquiry.mm87
-rw-r--r--src/bluetooth/qbluetoothservicediscoveryagent.cpp5
-rw-r--r--src/bluetooth/qbluetoothservicediscoveryagent_android.cpp42
5 files changed, 97 insertions, 43 deletions
diff --git a/src/bluetooth/doc/src/bluetooth-index.qdoc b/src/bluetooth/doc/src/bluetooth-index.qdoc
index 2a4f72bc..a0e2a048 100644
--- a/src/bluetooth/doc/src/bluetooth-index.qdoc
+++ b/src/bluetooth/doc/src/bluetooth-index.qdoc
@@ -41,7 +41,7 @@ Currently, the API is supported on the following platforms:
\li \l {Qt for Android}{Android}
\li \l {Qt for iOS}{iOS}
\li \l {Qt for Linux/X11}{Linux (BlueZ 4.x/5.x)}
- \li \l {Qt for OS X}{macOS}
+ \li \l \macos
\li \l {Qt for WinRT}{WinRT}
\li \l {Qt for Windows}{Win32}
\row
diff --git a/src/bluetooth/osx/osxbtcentralmanager.mm b/src/bluetooth/osx/osxbtcentralmanager.mm
index cadabbaf..41713909 100644
--- a/src/bluetooth/osx/osxbtcentralmanager.mm
+++ b/src/bluetooth/osx/osxbtcentralmanager.mm
@@ -1245,6 +1245,7 @@ QT_USE_NAMESPACE
if (notifier)
emit notifier->CBManagerError(QLowEnergyController::InvalidBluetoothAdapterError);
}
+ [self stopWatchers];
return;
}
@@ -1266,6 +1267,7 @@ QT_USE_NAMESPACE
if (notifier)
emit notifier->CBManagerError(QLowEnergyController::InvalidBluetoothAdapterError);
}
+ [self stopWatchers];
return;
}
@@ -1280,7 +1282,7 @@ QT_USE_NAMESPACE
}
} else {
// We actually handled all known states, but .. Core Bluetooth can change?
- Q_ASSERT_X(0, Q_FUNC_INFO, "invalid centra's state");
+ Q_ASSERT_X(0, Q_FUNC_INFO, "invalid central's state");
}
#pragma clang diagnostic pop
diff --git a/src/bluetooth/osx/osxbtledeviceinquiry.mm b/src/bluetooth/osx/osxbtledeviceinquiry.mm
index c56b6da3..70b96ab7 100644
--- a/src/bluetooth/osx/osxbtledeviceinquiry.mm
+++ b/src/bluetooth/osx/osxbtledeviceinquiry.mm
@@ -121,6 +121,11 @@ QT_END_NAMESPACE
QT_USE_NAMESPACE
+@interface QT_MANGLE_NAMESPACE(OSXBTLEDeviceInquiry)(PrivateAPI)
+- (void)stopScanSafe;
+- (void)stopNotifier;
+@end
+
@implementation QT_MANGLE_NAMESPACE(OSXBTLEDeviceInquiry)
{
LECBManagerNotifier *notifier;
@@ -147,17 +152,10 @@ QT_USE_NAMESPACE
- (void)dealloc
{
- if (manager) {
- [manager setDelegate:nil];
- if (internalState == InquiryActive)
- [manager stopScan];
- }
-
- if (notifier) {
- notifier->disconnect();
- notifier->deleteLater();
- }
-
+ [self stopScanSafe];
+ [manager setDelegate:nil];
+ [elapsedTimer cancelTimer];
+ [self stopNotifier];
[super dealloc];
}
@@ -166,7 +164,7 @@ QT_USE_NAMESPACE
Q_UNUSED(sender)
if (internalState == InquiryActive) {
- [manager stopScan];
+ [self stopScanSafe];
[manager setDelegate:nil];
internalState = InquiryFinished;
Q_ASSERT(notifier);
@@ -228,7 +226,7 @@ QT_USE_NAMESPACE
} else if (state == CBCentralManagerStateUnsupported || state == CBCentralManagerStateUnauthorized) {
#endif
if (internalState == InquiryActive) {
- [manager stopScan];
+ [self stopScanSafe];
// Not sure how this is possible at all,
// probably, can never happen.
internalState = ErrorPoweredOff;
@@ -244,8 +242,9 @@ QT_USE_NAMESPACE
#else
} else if (state == CBCentralManagerStatePoweredOff) {
#endif
+
+#ifndef Q_OS_MACOS
if (internalState == InquiryStarting) {
-#ifndef Q_OS_OSX
// On iOS a user can see at this point an alert asking to
// enable Bluetooth in the "Settings" app. If a user does so,
// we'll receive 'PoweredOn' state update later.
@@ -254,17 +253,19 @@ QT_USE_NAMESPACE
elapsedTimer.resetWithoutRetain([[GCDTimerObjC alloc] initWithDelegate:self]);
[elapsedTimer startWithTimeout:powerOffTimeoutMS step:300];
return;
+ }
#else
Q_UNUSED(powerOffTimeoutMS)
-#endif
- internalState = ErrorPoweredOff;
- emit notifier->CBManagerError(QBluetoothDeviceDiscoveryAgent::PoweredOffError);
- } else {
- [manager stopScan];
- emit notifier->CBManagerError(QBluetoothDeviceDiscoveryAgent::PoweredOffError);
- }
-
+#endif // Q_OS_MACOS
+ [elapsedTimer cancelTimer];
+ [self stopScanSafe];
[manager setDelegate:nil];
+ internalState = ErrorPoweredOff;
+ // On macOS we report PoweredOffError and our C++ owner will delete us
+ // (here we're kwnon as 'self'). Connection is Qt::QueuedConnection so we
+ // are apparently safe to call -stopNotifier after the signal.
+ emit notifier->CBManagerError(QBluetoothDeviceDiscoveryAgent::PoweredOffError);
+ [self stopNotifier];
} else {
// The following two states we ignore (from Apple's docs):
//"
@@ -281,19 +282,45 @@ QT_USE_NAMESPACE
#pragma clang diagnostic pop
}
-- (void)stop
+- (void)stopScanSafe
{
- if (internalState == InquiryActive)
- [manager stopScan];
+ // CoreBluetooth warns about API misused if we call stopScan in a state
+ // other than powered on. Hence this 'Safe' ...
+ if (!manager)
+ return;
- [elapsedTimer cancelTimer];
+#pragma clang diagnostic push
+#pragma clang diagnostic ignored "-Wunguarded-availability-new"
+
+ if (internalState == InquiryActive) {
+ const auto state = manager.data().state;
+ #if QT_IOS_PLATFORM_SDK_EQUAL_OR_ABOVE(__IPHONE_10_0) || QT_OSX_PLATFORM_SDK_EQUAL_OR_ABOVE(__MAC_10_13)
+ if (state == CBManagerStatePoweredOn)
+ #else
+ if (state == CBCentralManagerStatePoweredOn)
+ #endif
+ [manager stopScan];
+ }
+
+#pragma clang diagnostic pop
+}
+
+- (void)stopNotifier
+{
+ if (notifier) {
+ notifier->disconnect();
+ notifier->deleteLater();
+ notifier = nullptr;
+ }
+}
+- (void)stop
+{
+ [self stopScanSafe];
[manager setDelegate:nil];
+ [elapsedTimer cancelTimer];
+ [self stopNotifier];
internalState = InquiryCancelled;
-
- notifier->disconnect();
- notifier->deleteLater();
- notifier = nullptr;
}
- (void)centralManager:(CBCentralManager *)central
diff --git a/src/bluetooth/qbluetoothservicediscoveryagent.cpp b/src/bluetooth/qbluetoothservicediscoveryagent.cpp
index a5fc7654..da9c1386 100644
--- a/src/bluetooth/qbluetoothservicediscoveryagent.cpp
+++ b/src/bluetooth/qbluetoothservicediscoveryagent.cpp
@@ -169,6 +169,11 @@ QBluetoothServiceDiscoveryAgent::QBluetoothServiceDiscoveryAgent(QObject *parent
\note On WinRT the passed adapter address will be ignored.
+ \note On Android passing any \a deviceAdapter address is meaningless as Android 6.0 or later does not publish
+ the local Bluetooth address anymore. Subsequently, the passed adapter address can never be matched
+ against the local adapter address. Therefore the subsequent call to \l start() will always trigger
+ \l InvalidBluetoothAdapterError.
+
\sa error()
*/
QBluetoothServiceDiscoveryAgent::QBluetoothServiceDiscoveryAgent(const QBluetoothAddress &deviceAdapter, QObject *parent)
diff --git a/src/bluetooth/qbluetoothservicediscoveryagent_android.cpp b/src/bluetooth/qbluetoothservicediscoveryagent_android.cpp
index ce2911d3..ddc53421 100644
--- a/src/bluetooth/qbluetoothservicediscoveryagent_android.cpp
+++ b/src/bluetooth/qbluetoothservicediscoveryagent_android.cpp
@@ -55,21 +55,33 @@ QT_BEGIN_NAMESPACE
Q_DECLARE_LOGGING_CATEGORY(QT_BT_ANDROID)
QBluetoothServiceDiscoveryAgentPrivate::QBluetoothServiceDiscoveryAgentPrivate(
- QBluetoothServiceDiscoveryAgent *qp, const QBluetoothAddress &/*deviceAdapter*/)
+ QBluetoothServiceDiscoveryAgent *qp, const QBluetoothAddress &deviceAdapter)
: error(QBluetoothServiceDiscoveryAgent::NoError),
+ m_deviceAdapterAddress(deviceAdapter),
state(Inactive),
mode(QBluetoothServiceDiscoveryAgent::MinimalDiscovery),
singleDevice(false),
q_ptr(qp)
{
- QList<QBluetoothHostInfo> devices = QBluetoothLocalDevice::allDevices();
- Q_ASSERT(devices.count() <= 1); //Android only supports one device at the moment
-
- if (devices.isEmpty()) {
- error = QBluetoothServiceDiscoveryAgent::InvalidBluetoothAdapterError;
- errorString = QBluetoothServiceDiscoveryAgent::tr("Invalid Bluetooth adapter address");
- return;
+ // If a specific adapter address is requested we need to check it matches
+ // the current local adapter. If it does not match we emit
+ // InvalidBluetoothAdapterError when calling start()
+
+ bool createAdapter = true;
+ if (!deviceAdapter.isNull()) {
+ const QList<QBluetoothHostInfo> devices = QBluetoothLocalDevice::allDevices();
+ if (devices.isEmpty()) {
+ createAdapter = false;
+ } else {
+ auto match = [deviceAdapter](const QBluetoothHostInfo& info) {
+ return info.address() == deviceAdapter;
+ };
+
+ auto result = std::find_if(devices.begin(), devices.end(), match);
+ if (result == devices.end())
+ createAdapter = false;
+ }
}
if (QtAndroidPrivate::androidSdkVersion() < 15)
@@ -84,7 +96,8 @@ QBluetoothServiceDiscoveryAgentPrivate::QBluetoothServiceDiscoveryAgentPrivate(
The logic below must change once there is more than one adapter.
*/
- btAdapter = QAndroidJniObject::callStaticObjectMethod("android/bluetooth/BluetoothAdapter",
+ if (createAdapter)
+ btAdapter = QAndroidJniObject::callStaticObjectMethod("android/bluetooth/BluetoothAdapter",
"getDefaultAdapter",
"()Landroid/bluetooth/BluetoothAdapter;");
if (!btAdapter.isValid())
@@ -110,8 +123,15 @@ void QBluetoothServiceDiscoveryAgentPrivate::start(const QBluetoothAddress &addr
Q_Q(QBluetoothServiceDiscoveryAgent);
if (!btAdapter.isValid()) {
- error = QBluetoothServiceDiscoveryAgent::UnknownError;
- errorString = QBluetoothServiceDiscoveryAgent::tr("Platform does not support Bluetooth");
+ if (m_deviceAdapterAddress.isNull()) {
+ error = QBluetoothServiceDiscoveryAgent::UnknownError;
+ errorString = QBluetoothServiceDiscoveryAgent::tr("Platform does not support Bluetooth");
+ } else {
+ // specific adapter was requested which does not match the locally
+ // existing adapter
+ error = QBluetoothServiceDiscoveryAgent::InvalidBluetoothAdapterError;
+ errorString = QBluetoothServiceDiscoveryAgent::tr("Invalid Bluetooth adapter address");
+ }
//abort any outstanding discoveries
discoveredDevices.clear();