Details
-
Bug
-
Resolution: Done
-
P2: Important
-
5.3.2
-
None
Description
There is a flaw in the solution of QTBUG-40172: in Android versions below 4.2, the getServiceChannel call doesn't always return BluetoothDevice.ERROR in case of an error. It can also return -1. QBluetoothSocket only checks for BluetoothDevice.ERROR, so the result is that QBluetoothSocket tries to use channel -1 to connect, but this is an invalid channel.
More background info:
Up to Android 4.1 the getServiceChannel function calls a lower level function on the BluetoothService and return ERROR in case an exception is thrown.
/** @hide */ public int getServiceChannel(ParcelUuid uuid) { try { return sService.getRemoteServiceChannel(mAddress, uuid); } catch (RemoteException e) {Log.e(TAG, "", e);} return BluetoothDevice.ERROR; }
That lower level function however does not seem to throw any exception itself, but does return -1 in case of an error.
public int getRemoteServiceChannel(String address, ParcelUuid uuid) { mContext.enforceCallingOrSelfPermission(BLUETOOTH_PERM, "Need BLUETOOTH permission"); if (!isEnabledInternal()) return -1; if (!BluetoothAdapter.checkBluetoothAddress(address)) { return BluetoothDevice.ERROR; } // Check if we are recovering from a crash. if (mDeviceProperties.isEmpty()) { if (mDeviceProperties.updateCache(address) == null) return -1; } Map<ParcelUuid, Integer> value = mDeviceServiceChannelCache.get(address); if (value != null && value.containsKey(uuid)) return value.get(uuid); return -1; }
Starting from Android 4.2, this function always returns ERROR.
/** @hide */ public int getServiceChannel(ParcelUuid uuid) { //TODO(BT) /* try { return sService.getRemoteServiceChannel(this, uuid); } catch (RemoteException e) {Log.e(TAG, "", e);}*/ return BluetoothDevice.ERROR; }