BLE failing to disconnect in Android when using PROPERTY_INDICATE

New to Kotlin as well as Android. I’m writing an app that needs to connect to a peripheral device via BLE. In most cases, it works great: connects, discovers services, reads and writes characteristics, and disconnects. However, I’ve encountered a specific case that refuses to disconnect and it has me stumped.

The connection uses a number of characteristics set to various combinations of PROPERTY_READ, PROPERTY_INDICATE, and PROPERTY_NOTIFY. Most of the characteristics are only used periodically, but two of the characteristics are broadcasted every second and are set to PROPERTY_INDICATE. My disconnect procedure consists of calling gatt.disconnect(), waiting for the GattCallback to announce state has changed to STATE_DISCONNECTED, and then calling gatt.close() followed by gatt = null. In all but the problem scenario, this results in the peripheral device returning to advertising mode.

In the problem scenario, all of these steps happen as usual, but the peripheral never returns to advertising mode (until I either reset the peripheral device or restart my phone). Thus, it appears my phone (a Galaxy S9) is not actually disconnecting from the device.

Digging into this deeper, I’ve unearthed the following:

  • BluetoothManager.getConnectedDevices() returns 0 during this scenario after the disconnect process has completed.
  • Reducing the characteristic count has no effect. I have 9 total characteristics currently.
  • Staggering the updates of the two characteristics that are broadcasting every second (so they are a half second out of phase with each other) has no effect.

The problem goes away when I do either of the following:

  • I reduce the update rate of the two characteristics that are broadcasting every second to every two seconds
  • I change one of the two characteristics that is broadcasting every second from PROPERTY_INDICATE to PROPERTY_NOTIFY

Neither fix is ideal for my situation.

Any idea what is going on here?