I am developing an Android app that interfaces with a BLE device and recently stumbled across some strange behavior: when the app disconnects from the device, a few seconds later something else seems to establish the connection.
I am in the process of characterizing the issue more fully and have been focused on the Bluetooth MAP and PBAP profiles; they show up in the logs around the point of issue. I am unsure, however, if this is the root cause, nor have I found a workaround.
The app supports API 23-25. To date, I have only experienced the issue in phones with SIM cards present, which points again to PBAP since many phones seem to support this profile only with a SIM card. I haven't yet been able to reproduce on API 23, but for now those test phones do not have SIM cards.
The BLE device has nothing to do with automotive application, nor does it have the ability to deal with Contacts or Messaging. I haven't intentionally enabled any of this within the app. Furthermore, there is no pairing / bonding between my app and the device, nor does the device support pairing / bonding.
In most cases, the attempt to reconnect happens once, a few seconds after device disconnect via the app. Subsequent connect-disconnect sequences in the app have the same behavior. However, I have seen in at least one instance where the reconnects (outside of the app) continue indefinitely every few seconds.
The only thing that seems to resolve the issue short-term is to cycle Bluetooth on the phone, or force-stop the Bluetooth Share process. I don't believe the reconnects come back on their own, but it is common that they do reappear once the user connects-disconnects with the device through my app.
I am not very familiar with PBAP / MAP so am unaware how they get enabled or, if possible, how to disable them. I am not sure if they are the culprit, but they appear in the logs at the moment of reconnect.
Following is the log statements around the point of disconnection and subsequent reconnection. The interface name here is "Foo04" with MAC = B0:B4:48:E8:FA:04.
03-31 14:27:44.305 D/RxBle#Radio(14105): STARTED RxBleRadioOperationDisconnect(186827491)
03-31 14:27:44.319 D/BluetoothManager(14105): getConnectionState()
03-31 14:27:44.320 D/BluetoothManager(14105): getConnectedDevices
03-31 14:27:44.332 D/BluetoothGatt(14105): cancelOpen() - device: B0:B4:48:E8:FA:04
03-31 14:27:44.334 D/BtGatt.GattService(13168): clientDisconnect() - address=B0:B4:48:E8:FA:04, connId=5
03-31 14:27:44.339 E/bt_btif (13168): bta_gattc_mark_bg_conn unable to find the bg connection mask for: b0:b4:48:e8:fa:04
03-31 14:27:44.340 D/BtGatt.GattService(13168): onDisconnected() - clientIf=5, connId=5, address=B0:B4:48:E8:FA:04
03-31 14:27:44.341 D/BluetoothGatt(14105): onClientConnectionState() - status=0 clientIf=5 device=B0:B4:48:E8:FA:04
03-31 14:27:44.342 D/RxBle#BluetoothGatt(14105): onConnectionStateChange newState=0 status=0
03-31 14:27:44.345 D/RxBle#Radio(14105): FINISHED RxBleRadioOperationDisconnect(186827491)
03-31 14:27:44.352 D/BluetoothGatt(14105): close()
03-31 14:27:44.352 D/BluetoothGatt(14105): unregisterApp() - mClientIf=5
03-31 14:27:44.354 D/BtGatt.GattService(13168): unregisterClient() - clientIf=5
03-31 14:27:45.376 W/bt_l2cap(13168): l2cble_process_conn_update_evt: Error status: 22
03-31 14:27:45.377 W/bt_btif (13168): bta_gattc_conn_cback() - cif=3 connected=0 conn_id=3 reason=0x0016
03-31 14:27:45.377 W/bt_btif (13168): bta_gattc_conn_cback() - cif=4 connected=0 conn_id=4 reason=0x0016
03-31 14:27:45.377 I/bt_btm_sec(13168): btm_sec_disconnected clearing pending flag handle:13 reason:22
03-31 14:27:45.381 E/BluetoothRemoteDevices(13168): state12newState1
03-31 14:27:45.393 D/BluetoothMapService(13168): onReceive
03-31 14:27:45.393 D/BluetoothMapService(13168): onReceive: android.bluetooth.device.action.ACL_DISCONNECTED
03-31 14:27:45.402 D/BluetoothPbapReceiver(13168): PbapReceiver onReceive action =
03-31 14:27:45.404 D/BluetoothPbapReceiver(13168): Calling start service with action = null
03-31 14:27:45.405 I/TrustAgent.Tracker(15208): [BluetoothConnectionTracker] Bluetooth disconnect broadast for Foo04 B0:B4:48:E8:FA:04
03-31 14:27:46.407 W/bt_smp (13168): smp_br_connect_callback is called on unexpected transport 2
03-31 14:27:46.408 W/bt_btif (13168): bta_dm_acl_change info: 0x0
03-31 14:27:46.408 I/bt_bta_dm(13168): bta_dm_gatt_disc_result service_id_uuid_len=2
03-31 14:27:46.408 I/bt_bta_dm(13168): bta_dm_gatt_disc_result service_id_uuid_len=2
03-31 14:27:46.408 D/bt_btif_dm(13168): remote version info [b0:b4:48:e8:fa:04]: 0, 0, 0
03-31 14:27:46.408 I/bt_bta_dm(13168): bta_dm_gatt_disc_result service_id_uuid_len=2
03-31 14:27:46.408 I/bt_bta_dm(13168): bta_dm_gatt_disc_result service_id_uuid_len=16
03-31 14:27:46.408 I/bt_bta_dm(13168): bta_dm_gatt_disc_result service_id_uuid_len=2
03-31 14:27:46.412 E/BluetoothRemoteDevices(13168): state12newState0
03-31 14:27:46.457 I/TrustAgent.Tracker(15208): [BluetoothConnectionTracker] Bluetooth connect broadast for Foo04 B0:B4:48:E8:FA:04
03-31 14:27:47.317 I/WCNSS_FILTER(13194): ibs_msm_serial_clock_vote: vote UART CLK OFF using UART driver's ioctl()
03-31 14:27:48.421 I/WCNSS_FILTER(13194): ibs_msm_serial_clock_vote: vote UART CLK ON using UART driver's ioctl()
03-31 14:27:48.483 W/bt_btif (13168): bta_gattc_conn_cback() - cif=3 connected=0 conn_id=3 reason=0x0016
03-31 14:27:48.483 W/bt_btif (13168): bta_gattc_conn_cback() - cif=4 connected=0 conn_id=4 reason=0x0016
03-31 14:27:48.483 I/bt_btm_sec(13168): btm_sec_disconnected clearing pending flag handle:14 reason:22
03-31 14:27:48.488 E/BluetoothRemoteDevices(13168): state12newState1
03-31 14:27:48.506 D/BluetoothMapService(13168): onReceive
03-31 14:27:48.506 D/BluetoothMapService(13168): onReceive: android.bluetooth.device.action.ACL_DISCONNECTED
03-31 14:27:48.524 D/BluetoothPbapReceiver(13168): PbapReceiver onReceive action = android.bluetooth.device.action.ACL_DISCONNECTED
03-31 14:27:48.527 D/BluetoothPbapReceiver(13168): Calling start service with action = null
03-31 14:27:48.530 I/TrustAgent.Tracker(15208): [BluetoothConnectionTracker] Bluetooth disconnect broadast for Foo04 B0:B4:48:E8:FA:04
03-31 14:27:49.430 I/WCNSS_FILTER(13194): ibs_msm_serial_clock_vote: vote UART CLK OFF using UART driver's ioctl()
Further Investigation
I posted a related question in Android BLE ACL_DISCONNECTED sometimes delayed.
One commonality among the devices where I've seen the problem has been the existence of a SIM card, but another one is API 24 or 25. I haven't yet been able to reproduce on an API 23 device or, regardless of version, one without a SIM card physically installed.
After even further investigation, I'm less suspect of the SIM card, and more of the API version. There are several outstanding (or recently fixed) bugs that have related behavior, some of which points to API versions > 23; however, I have subsequently been able to reproduce on API 23.
- BLE: Having two pending direct connections and cancelling the second one does not work
- BLE: Disconnecting/closing GATT directly after connect sometimes has no effect due to race conditions
- BLE: Closing gatt object or app does not remove pending connection since Android N
- Race condition in BluetoothGatt when using BluetoothDevice#connectGatt()
I'm feeling this has little to do with PBAP / MAP profiles. Rather, the existence of them in the logs points simply to these profiles being activated with any BLE disconnection. While not manifesting the reconnection behavior, I was able to see similar PBAP / MAP activation when messing with a TI SensorTag: these profiles again logged any disconnect (unrelated to my application).
List of Affected Devices
I've been able to reproduce this issue, to varying degrees, on the following devices:
- Samsung S6 - API 23
- Samsung S7 - API 23
- Samsung S7 Edge - API 24
- Sony Xperia Z5 Compact - API 24
- Motorola Droid Turbo 2 - API 24
- Nexus 5x - API 25
- Google Pixel - API 25