Details
-
Bug
-
Resolution: Done
-
P2: Important
-
5.3.1
-
None
-
android
Description
Hello. Sorry for my english.
I was trying to connect a bluetooth device (not an android) using RFcomm socket. But It was failing with following log output.
D/Qt (25579): ../sprcc/src/Bluetooth/BluetoothClientWorker.cpp:37 (void BluetoothClientWorker::connectToHost(const QBluetoothAddress&, const QBluetoothUuid&)): [BluetoothClientWorker] Connecting using "{00001101-0000-1000-8000-00805f9b34fb}" D/Qt (25579): ../sprcc/src/Bluetooth/BluetoothClientWorker.cpp:130 (void BluetoothClientWorker::stateChanged(QBluetoothSocket::SocketState)): [BluetoothClientWorker] State: "Connecting" W/BluetoothAdapter(25579): getBluetoothService() called with no BluetoothManagerCallback D/BTIF_SOCK( 946): service_uuid: 00001101-0000-1000-8000-00805f9b34fb D/BluetoothSocket(25579): connect(), SocketState: INIT, mPfd: {ParcelFileDescriptor: FileDescriptor[68]} W/bt-btif ( 946): info:x10 D/ ( 946): remote version info [00:12:ff:c7:00:c9]: 4, a, 12e9 D/BluetoothManagerService( 451): Message: 20 D/BluetoothManagerService( 451): Added callback: android.bluetooth.IBluetoothManagerCallback$Stub$Proxy@428d5548:true W/bt-sdp ( 946): process_service_search_attr_rsp E/bt-btif ( 946): DISCOVERY_COMP_EVT slot id:129, failed to find channle, status:1, scn:0 W/bt-btif ( 946): invalid rfc slot id: 129 W/System.err(25579): java.io.IOException: read failed, socket might closed or timeout, read ret: -1 W/System.err(25579): at android.bluetooth.BluetoothSocket.readAll(BluetoothSocket.java:505) W/System.err(25579): at android.bluetooth.BluetoothSocket.readInt(BluetoothSocket.java:516) W/System.err(25579): at android.bluetooth.BluetoothSocket.connect(BluetoothSocket.java:320) W/System.err(25579): at dalvik.system.NativeStart.run(Native Method) D/Qt (25579): ../sprcc/src/Bluetooth/BluetoothClientWorker.cpp:93 (void BluetoothClientWorker::socketError(QBluetoothSocket::SocketError)): [BluetoothClientWorker] Error: "Service not found error." D/Qt (25579): ../sprcc/src/Bluetooth/BluetoothClientWorker.cpp:130 (void BluetoothClientWorker::stateChanged(QBluetoothSocket::SocketState)): [BluetoothClientWorker] State: "Unconnected" D/Finsky (13387): [1] 5.onFinished: Installation state replication succeeded. D/btif_config_util( 946): btif_config_save_file(L153): in file name:/data/misc/bluedroid/bt_config.new E/bt-btm ( 946): btm_sec_disconnected - Clearing Pending flag
Then I find out this was a chronic problem of Android and I found this patch. In fact this patch is everywhere.
https://github.com/pires/android-obd-reader/commit/2ae0d214abf4c02e6d3b1ef07a165c82c6ef13a7
I did applied into qtconnectivity
qbluetoothsocket_android.cpp
void QBluetoothSocketPrivate::connectToServiceConc(const QBluetoothAddress &address, const QBluetoothUuid &uuid, QIODevice::OpenMode openMode) { Q_Q(QBluetoothSocket); Q_UNUSED(openMode); if (!adapter.isValid()) { qCWarning(QT_BT_ANDROID) << "Device does not support Bluetooth"; errorString = QBluetoothSocket::tr("Device does not support Bluetooth"); q->setSocketError(QBluetoothSocket::NetworkError); q->setSocketState(QBluetoothSocket::UnconnectedState); return; } const int state = adapter.callMethod<jint>("getState"); if (state != 12 ) { //BluetoothAdapter.STATE_ON qCWarning(QT_BT_ANDROID) << "Bt device offline"; errorString = QBluetoothSocket::tr("Device is powered off"); q->setSocketError(QBluetoothSocket::NetworkError); q->setSocketState(QBluetoothSocket::UnconnectedState); return; } QAndroidJniEnvironment env; QAndroidJniObject inputString = QAndroidJniObject::fromString(address.toString()); remoteDevice = adapter.callObjectMethod("getRemoteDevice", "(Ljava/lang/String;)Landroid/bluetooth/BluetoothDevice;", inputString.object<jstring>()); if (env->ExceptionCheck()) { env->ExceptionDescribe(); env->ExceptionClear(); errorString = QBluetoothSocket::tr("Cannot access address %1", "%1 = Bt address e.g. 11:22:33:44:55:66").arg(address.toString()); q->setSocketError(QBluetoothSocket::HostNotFoundError); q->setSocketState(QBluetoothSocket::UnconnectedState); return; } //cut leading { and trailing } {xxx-xxx} QString tempUuid = uuid.toString(); tempUuid.chop(1); //remove trailing '}' tempUuid.remove(0, 1); //remove first '{' inputString = QAndroidJniObject::fromString(tempUuid); QAndroidJniObject uuidObject = QAndroidJniObject::callStaticObjectMethod("java/util/UUID", "fromString", "(Ljava/lang/String;)Ljava/util/UUID;", inputString.object<jstring>()); socketObject = remoteDevice.callObjectMethod("createRfcommSocketToServiceRecord", "(Ljava/util/UUID;)Landroid/bluetooth/BluetoothSocket;", uuidObject.object<jobject>()); if (env->ExceptionCheck()) { env->ExceptionDescribe(); env->ExceptionClear(); socketObject = remoteDevice = QAndroidJniObject(); errorString = QBluetoothSocket::tr("Cannot connect to %1 on %2", "%1 = uuid, %2 = Bt address").arg(uuid.toString()).arg(address.toString()); q->setSocketError(QBluetoothSocket::ServiceNotFoundError); q->setSocketState(QBluetoothSocket::UnconnectedState); return; } socketObject.callMethod<void>("connect"); if (env->ExceptionCheck() || socketObject.callMethod<jboolean>("isConnected") == JNI_FALSE) { if (env->ExceptionCheck()) { env->ExceptionDescribe(); env->ExceptionClear(); } qCWarning(QT_BT_ANDROID) << "Falling back to workaround."; jclass remoteDeviceClazz = env->GetObjectClass(remoteDevice.object()); if (!remoteDeviceClazz) { qCWarning(QT_BT_ANDROID) << "Could not found GetObjectClass of BluetoothDevice."; socketObject = remoteDevice = QAndroidJniObject(); q->setSocketError(QBluetoothSocket::ServiceNotFoundError); q->setSocketState(QBluetoothSocket::UnconnectedState); return; } jmethodID getClassMethod = env->GetMethodID(remoteDeviceClazz, "getClass", "()Ljava/lang/Class;"); if (!getClassMethod) { qCWarning(QT_BT_ANDROID) << "getClass method could not found."; socketObject = remoteDevice = QAndroidJniObject(); q->setSocketError(QBluetoothSocket::ServiceNotFoundError); q->setSocketState(QBluetoothSocket::UnconnectedState); return; } QAndroidJniObject remoteDeviceClass = QAndroidJniObject(env->CallObjectMethod(remoteDevice.object(), getClassMethod)); if (!remoteDeviceClass.isValid()) { qCWarning(QT_BT_ANDROID) << "Could not invoke getClass from BluetoothDevice."; socketObject = remoteDevice = QAndroidJniObject(); q->setSocketError(QBluetoothSocket::ServiceNotFoundError); q->setSocketState(QBluetoothSocket::UnconnectedState); return; } jclass classClass = env->FindClass("java/lang/Class"); jclass integerClass = env->FindClass("java/lang/Integer"); jfieldID integerType = env->GetStaticFieldID(integerClass, "TYPE", "Ljava/lang/Class;"); jobject integerObject = env->GetStaticObjectField(integerClass, integerType); if (!integerObject) { qCWarning(QT_BT_ANDROID) << "Could not get Integer.TYPE"; socketObject = remoteDevice = QAndroidJniObject(); q->setSocketError(QBluetoothSocket::ServiceNotFoundError); q->setSocketState(QBluetoothSocket::UnconnectedState); return; } jobjectArray paramTypes = env->NewObjectArray(1, classClass, integerObject); if (!paramTypes) { qCWarning(QT_BT_ANDROID) << "Could not create new Class[]{Integer.TYPE}"; if (env->ExceptionCheck()) { env->ExceptionDescribe(); env->ExceptionClear(); } socketObject = remoteDevice = QAndroidJniObject(); q->setSocketError(QBluetoothSocket::ServiceNotFoundError); q->setSocketState(QBluetoothSocket::UnconnectedState); return; } QAndroidJniObject method = remoteDeviceClass.callObjectMethod( "getMethod", "(Ljava/lang/String;[Ljava/lang/Class;)Ljava/lang/reflect/Method;", QAndroidJniObject::fromString("createInsecureRfcommSocket").object<jstring>(), paramTypes); if (!method.isValid() || env->ExceptionCheck()) { qCWarning(QT_BT_ANDROID) << "Could not invoke getMethod"; if (env->ExceptionCheck()) { env->ExceptionDescribe(); env->ExceptionClear(); } socketObject = remoteDevice = QAndroidJniObject(); q->setSocketError(QBluetoothSocket::ServiceNotFoundError); q->setSocketState(QBluetoothSocket::UnconnectedState); return; } jclass methodClass = env->GetObjectClass(method.object()); jmethodID invokeMethodId = env->GetMethodID(methodClass, "invoke", "(Ljava/lang/Object;[Ljava/lang/Object;)Ljava/lang/Object;"); if (!invokeMethodId) { qCWarning(QT_BT_ANDROID) << "Could not invoke method."; socketObject = remoteDevice = QAndroidJniObject(); q->setSocketError(QBluetoothSocket::ServiceNotFoundError); q->setSocketState(QBluetoothSocket::UnconnectedState); return; } jmethodID valueOfMethodId = env->GetStaticMethodID(integerClass, "valueOf", "(I)Ljava/lang/Integer;"); jclass objectClass = env->FindClass("java/lang/Object"); jobjectArray invokeParams = env->NewObjectArray(1, objectClass, env->CallStaticObjectMethod(integerClass, valueOfMethodId, 1)); jobject invokeResult = env->CallObjectMethod(method.object(), invokeMethodId, remoteDevice.object(), invokeParams); if (!invokeResult) { qCWarning(QT_BT_ANDROID) << "Invoke Resulted with error."; if (env->ExceptionCheck()) { env->ExceptionDescribe(); env->ExceptionClear(); } socketObject = remoteDevice = QAndroidJniObject(); q->setSocketError(QBluetoothSocket::ServiceNotFoundError); q->setSocketState(QBluetoothSocket::UnconnectedState); return; } else { qCWarning(QT_BT_ANDROID) << "Invoke Result successfull."; } socketObject = QAndroidJniObject(invokeResult); socketObject.callMethod<void>("connect"); if (env->ExceptionCheck() || socketObject.callMethod<jboolean>("isConnected") == JNI_FALSE) { if (env->ExceptionCheck()) { env->ExceptionDescribe(); env->ExceptionClear(); } socketObject = remoteDevice = QAndroidJniObject(); errorString = QBluetoothSocket::tr("Connection to service failed"); qCWarning(QT_BT_ANDROID) << errorString; q->setSocketError(QBluetoothSocket::ServiceNotFoundError); q->setSocketState(QBluetoothSocket::UnconnectedState); return; } } if (inputThread) { inputThread->deleteLater(); inputThread = 0; } inputStream = socketObject.callObjectMethod("getInputStream", "()Ljava/io/InputStream;"); outputStream = socketObject.callObjectMethod("getOutputStream", "()Ljava/io/OutputStream;"); if (env->ExceptionCheck() || !inputStream.isValid() || !outputStream.isValid()) { env->ExceptionDescribe(); env->ExceptionClear(); //close socket again socketObject.callMethod<void>("close"); if (env->ExceptionCheck()) { env->ExceptionDescribe(); env->ExceptionClear(); } socketObject = inputStream = outputStream = remoteDevice = QAndroidJniObject(); errorString = QBluetoothSocket::tr("Obtaining streams for service failed"); q->setSocketError(QBluetoothSocket::NetworkError); q->setSocketState(QBluetoothSocket::UnconnectedState); return; } inputThread = new InputStreamThread(this); QObject::connect(inputThread, SIGNAL(dataAvailable()), q, SIGNAL(readyRead()), Qt::QueuedConnection); QObject::connect(inputThread, SIGNAL(error(int)), this, SLOT(inputThreadError(int)), Qt::QueuedConnection); if (!inputThread->run()) { //close socket again socketObject.callMethod<void>("close"); if (env->ExceptionCheck()) { env->ExceptionDescribe(); env->ExceptionClear(); } socketObject = inputStream = outputStream = remoteDevice = QAndroidJniObject(); delete inputThread; inputThread = 0; errorString = QBluetoothSocket::tr("Input stream thread cannot be started"); q->setSocketError(QBluetoothSocket::NetworkError); q->setSocketState(QBluetoothSocket::UnconnectedState); return; } q->setSocketState(QBluetoothSocket::ConnectedState); emit q->connected(); }
And yes... It worked with following output.
D/Qt (26912): ../sprcc/src/Bluetooth/BluetoothClientWorker.cpp:37 (void BluetoothClientWorker::connectToHost(const QBluetoothAddress&, const QBluetoothUuid&)): [BluetoothClientWorker] Connecting using "{00001101-0000-1000-8000-00805f9b34fb}" D/Qt (26912): ../sprcc/src/Bluetooth/BluetoothClientWorker.cpp:130 (void BluetoothClientWorker::stateChanged(QBluetoothSocket::SocketState)): [BluetoothClientWorker] State: "Connecting" W/BluetoothAdapter(26912): getBluetoothService() called with no BluetoothManagerCallback D/BTIF_SOCK( 946): service_uuid: 00001101-0000-1000-8000-00805f9b34fb D/BluetoothSocket(26912): connect(), SocketState: INIT, mPfd: {ParcelFileDescriptor: FileDescriptor[68]} W/bt-sdp ( 946): SDP - Rcvd conn cnf with error: 0x4 CID 0x40 E/bt-btif ( 946): DISCOVERY_COMP_EVT slot id:130, failed to find channle, status:1, scn:0 W/System.err(26912): java.io.IOException: read failed, socket might closed or timeout, read ret: -1 W/bt-btif ( 946): invalid rfc slot id: 130 W/System.err(26912): at android.bluetooth.BluetoothSocket.readAll(BluetoothSocket.java:505) W/System.err(26912): at android.bluetooth.BluetoothSocket.readInt(BluetoothSocket.java:516) W/System.err(26912): at android.bluetooth.BluetoothSocket.connect(BluetoothSocket.java:320) W/System.err(26912): at dalvik.system.NativeStart.run(Native Method) W/Qt (26912): /Developer/Native/qtconnectivity/src/bluetooth/qbluetoothsocket_android.cpp:166 (void QBluetoothSocketPrivate::connectToServiceConc(const QBluetoothAddress&, const QBluetoothUuid&, QIODevice::OpenMode)): qt.bluetooth.android: Falling back to workaround. W/Qt (26912): /Developer/Native/qtconnectivity/src/bluetooth/qbluetoothsocket_android.cpp:283 (void QBluetoothSocketPrivate::connectToServiceConc(const QBluetoothAddress&, const QBluetoothUuid&, QIODevice::OpenMode)): qt.bluetooth.android: Invoke Result successfull. W/BluetoothAdapter(26912): getBluetoothService() called with no BluetoothManagerCallback D/BluetoothSocket(26912): connect(), SocketState: INIT, mPfd: {ParcelFileDescriptor: FileDescriptor[69]} W/bt-btif ( 946): info:x10 D/ ( 946): remote version info [00:12:ff:c7:00:c9]: 4, a, 12e9 I/ActivityManager( 451): Start proc com.skype.raider for broadcast com.skype.raider/com.skype.android.audio.BluetoothReceiver: pid=27019 uid=10098 gids={50098, 3003, 3002, 1028, 1015} D/dalvikvm(27019): Trying to load lib /data/app-lib/com.skype.raider-1/libSkypeAndroid.so 0x41c68e00 W/linker (27019): libSkypeAndroid.so has text relocations. This is wasting memory and is a security risk. Please fix. D/dalvikvm(27019): Added shared lib /data/app-lib/com.skype.raider-1/libSkypeAndroid.so 0x41c68e00 W/bt-btif ( 946): new conn_srvc id:26, app_id:1 W/bt-btif ( 946): bta_dm_pm_ssr conn_srvc id:26, app_id:1 W/bt-btif ( 946): bta_dm_pm_ssr:2, lat:1200 D/Qt (26912): ../sprcc/src/Bluetooth/BluetoothClientWorker.cpp:130 (void BluetoothClientWorker::stateChanged(QBluetoothSocket::SocketState)): [BluetoothClientWorker] State: "Connected" D/dalvikvm(27019): GC_CONCURRENT freed 317K, 11% free 3154K/3536K, paused 3ms+2ms, total 22ms D/dalvikvm(27019): GC_CONCURRENT freed 404K, 13% free 3172K/3640K, paused 2ms+2ms, total 12ms D/dalvikvm(27019): GC_CONCURRENT freed 368K, 13% free 3190K/3640K, paused 1ms+1ms, total 8ms D/dalvikvm(27019): GC_CONCURRENT freed 354K, 12% free 3221K/3640K, paused 1ms+1ms, total 8ms D/dalvikvm(27019): GC_CONCURRENT freed 437K, 14% free 3236K/3736K, paused 2ms+1ms, total 9ms D/dalvikvm(27019): GC_CONCURRENT freed 431K, 14% free 3272K/3768K, paused 1ms+2ms, total 14ms D/dalvikvm(27019): GC_CONCURRENT freed 405K, 13% free 3356K/3824K, paused 1ms+15ms, total 30ms D/dalvikvm(27019): GC_CONCURRENT freed 420K, 13% free 3365K/3848K, paused 2ms+11ms, total 23ms D/dalvikvm(27019): GC_CONCURRENT freed 339K, 11% free 3445K/3860K, paused 1ms+2ms, total 24ms D/dalvikvm(27019): GC_CONCURRENT freed 372K, 10% free 3520K/3896K, paused 2ms+1ms, total 15ms D//Ln.java:218(27019): main Configuring Logging, minimum log level is INFO D/dalvikvm(27019): GC_CONCURRENT freed 448K, 13% free 3458K/3972K, paused 2ms+1ms, total 10ms D/dalvikvm(27019): GC_FOR_ALLOC freed 49K, 12% free 3531K/4012K, paused 7ms, total 7ms D/dalvikvm(27019): GC_FOR_ALLOC freed 81K, 12% free 3641K/4092K, paused 8ms, total 8ms D/BluetoothManagerService( 451): Message: 20 D/BluetoothManagerService( 451): Added callback: android.bluetooth.IBluetoothManagerCallback$Stub$Proxy@42484b68:true D/btif_config_util( 946): btif_config_save_file(L153): in file name:/data/misc/bluedroid/bt_config.new
Is there any way to implement this patch? Or is it too ugly?
Attachments
Issue Links
- resulted in
-
QTBUG-56253 QBluetoothSocket fallback connect will always fail on Android 4.4 or later
- Closed