From f8c0572ddcd0cf152cfcf9f1d5478e520a6a457e Mon Sep 17 00:00:00 2001 From: Alex Blasche Date: Tue, 25 Sep 2018 10:57:07 +0200 Subject: Properly handle pin code pairing on Android Most likely this paring variant was forgotten when Android support for QBluetoothLocalDevice was implemented. This variant is rather uncommon and Android's default pairing handler are likely to automatically handle such requests too. Fixes: QTBUG-70295 Change-Id: I618242da415574245e5a213a6e34f190c685c8e9 Reviewed-by: Oliver Wolff --- .../android/localdevicebroadcastreceiver.cpp | 41 ++++++++++++++++++++++ .../android/localdevicebroadcastreceiver_p.h | 1 + src/bluetooth/qbluetoothlocaldevice_android.cpp | 11 ++++++ src/bluetooth/qbluetoothlocaldevice_p.h | 1 + 4 files changed, 54 insertions(+) (limited to 'src') diff --git a/src/bluetooth/android/localdevicebroadcastreceiver.cpp b/src/bluetooth/android/localdevicebroadcastreceiver.cpp index c6cb3680..2d247574 100644 --- a/src/bluetooth/android/localdevicebroadcastreceiver.cpp +++ b/src/bluetooth/android/localdevicebroadcastreceiver.cpp @@ -39,6 +39,7 @@ #include #include +#include #include "localdevicebroadcastreceiver_p.h" #include "android/jni_android_p.h" @@ -186,6 +187,46 @@ void LocalDeviceBroadcastReceiver::onReceive(JNIEnv *env, jobject context, jobje switch (variant) { case -1: //ignore -> no pairing variant set return; + case 0: //BluetoothDevice.PAIRING_VARIANT_PIN + { + //generate a random key + const QString pin = QStringLiteral("%1").arg(QRandomGenerator::global()->bounded(1000000), + 6, 10, QLatin1Char('0')); + const QAndroidJniObject javaPin = QAndroidJniObject::fromString(pin); + + //get BluetoothDevice + keyExtra = valueForStaticField(JavaNames::BluetoothDevice, JavaNames::ExtraDevice); + QAndroidJniObject bluetoothDevice = + intentObject.callObjectMethod("getParcelableExtra", + "(Ljava/lang/String;)Landroid/os/Parcelable;", + keyExtra.object()); + if (!bluetoothDevice.isValid()) + return; + + QAndroidJniObject bytePin = QAndroidJniObject::callStaticObjectMethod("android/bluetooth/BluetoothDevice", + "convertPinToBytes", + "(Ljava/lang/String;)[B", + javaPin.object()); + if (!bytePin.isValid()) { + if (env->ExceptionCheck()) { + env->ExceptionDescribe(); + env->ExceptionClear(); + } + return; + } + + jboolean result = bluetoothDevice.callMethod("setPin", "([B)Z", bytePin.object()); + if (!result) { + if (env->ExceptionCheck()) { + env->ExceptionDescribe(); + env->ExceptionClear(); + } + return; + } + + const QBluetoothAddress address(bluetoothDevice.callObjectMethod("getAddress").toString()); + emit pairingDisplayPinCode(address, pin); + } case 2: //BluetoothDevice.PAIRING_VARIANT_PASSKEY_CONFIRMATION { keyExtra = valueForStaticField(JavaNames::BluetoothDevice, diff --git a/src/bluetooth/android/localdevicebroadcastreceiver_p.h b/src/bluetooth/android/localdevicebroadcastreceiver_p.h index c6ae424d..09e50fb1 100644 --- a/src/bluetooth/android/localdevicebroadcastreceiver_p.h +++ b/src/bluetooth/android/localdevicebroadcastreceiver_p.h @@ -72,6 +72,7 @@ signals: void pairingStateChanged(const QBluetoothAddress &address, QBluetoothLocalDevice::Pairing pairing); void connectDeviceChanges(const QBluetoothAddress &address, bool isConnectEvent); void pairingDisplayConfirmation(const QBluetoothAddress &address, const QString& pin); + void pairingDisplayPinCode(const QBluetoothAddress &address, const QString& pin); private: int previousScanMode; QAndroidJniObject pairingDevice; diff --git a/src/bluetooth/qbluetoothlocaldevice_android.cpp b/src/bluetooth/qbluetoothlocaldevice_android.cpp index f36e184c..0144a5ef 100644 --- a/src/bluetooth/qbluetoothlocaldevice_android.cpp +++ b/src/bluetooth/qbluetoothlocaldevice_android.cpp @@ -73,6 +73,8 @@ QBluetoothLocalDevicePrivate::QBluetoothLocalDevicePrivate( this, SLOT(processConnectDeviceChanges(QBluetoothAddress, bool))); connect(receiver, SIGNAL(pairingDisplayConfirmation(QBluetoothAddress, QString)), this, SLOT(processDisplayConfirmation(QBluetoothAddress, QString))); + connect(receiver, &LocalDeviceBroadcastReceiver::pairingDisplayPinCode, + this, &QBluetoothLocalDevicePrivate::processDisplayPinCode); } QBluetoothLocalDevicePrivate::~QBluetoothLocalDevicePrivate() @@ -215,6 +217,15 @@ void QBluetoothLocalDevicePrivate::processDisplayConfirmation(const QBluetoothAd return; emit q_ptr->pairingDisplayConfirmation(address, pin); +} + +void QBluetoothLocalDevicePrivate::processDisplayPinCode(const QBluetoothAddress &address, const QString &pin) +{ + // only send pairing notification for pairing requests issued by + // this QBluetoothLocalDevice instance + if (pendingPairing(address) == -1) + return; + emit q_ptr->pairingDisplayPinCode(address, pin); } diff --git a/src/bluetooth/qbluetoothlocaldevice_p.h b/src/bluetooth/qbluetoothlocaldevice_p.h index 038effcd..8752504d 100644 --- a/src/bluetooth/qbluetoothlocaldevice_p.h +++ b/src/bluetooth/qbluetoothlocaldevice_p.h @@ -113,6 +113,7 @@ private slots: QBluetoothLocalDevice::Pairing pairing); void processConnectDeviceChanges(const QBluetoothAddress &address, bool isConnectEvent); void processDisplayConfirmation(const QBluetoothAddress &address, const QString &pin); + void processDisplayPinCode(const QBluetoothAddress &address, const QString &pin); private: QBluetoothLocalDevice *q_ptr; -- cgit v1.2.3