This post is older than 2 years and might not be relevant anymore
More Info: Consider searching for newer posts

Refreshing cached services on bonded peer after DFU

Hi,

We're using bonding between our peripheral HID device and 3rd party central devices. Our device runs on a 52832 board with SDK 14.0.0 and SD 5.0.0.

We've run into a problem with GATT service caching on Android devices. The problem occurs after a DFU where we add a new report to the HID service.

ble_dfu_buttonless_bootloader_start_prepare() is called as to notify the peers about the service change, but on Android the services don't seem to refresh.

We're seeing bad behavior when sending HID messages - it seems the Android OS interprets the commands incorrectly, probably because it still has the old reports cached.

We have an Android App that performs the DFU using Nordic's SDK, and when the update is done, we attempt to refresh and rediscover the services unsuccessfully.

We tried using the BluetoothGatt.refresh() method as discussed here: https://github.com/Polidea/RxAndroidBle/issues/53 but it doesn't seem to have any effect.

Unpairing and re-pairing or just turning Bluetooth off and on again seems to solve the issue, but we'd like to avoid that since it requires user intervention.

We might try to implement an automatic mechanism to unpair and re-pair on the central, but we're interested to see if there's another possible way to refresh the services.

Thanks!

  • Hi Oded, 

    Which Android version are you using? Our Anderoid developer informed me that Android version 4.3-5.0 (prehaps 5.1 as well) and 8.0-9.0 do not enable Service Changed indications after bonding. It should be done automatically, but it's not on those versions. 

    So, make sure that indications of the Service Changed characteristic is enabled and that sd_ble_gatts_service_changed() call made from the bootloader includes the correct start and end handle values. 

    I assume that you're using our Android DFU Library in your Android app. Make sure that you're using the latest version, v1.7.0 other wise you will run in to the issue described here.

    Do you have a sniffer trace of the communication between the Android device and the nRF52832? It would be interesting to see if the Service Changed Indication is sent from the NRF52832 to the Android device. 

    If the SC indication is enabled and properly handled by the Android device, then another possible cause could be the following:

    After re-connection to the new app and resuming encryption, the target sends the SC indication and the Android will do the service discovery. Here, care must be taken to make sure that indication is correctly received.  After getting onConnectionStateChanged on bonded device we reommend waiting 1.6 second before calling discoverServices(), to make sure the indication was received, and the new service discovery was complete, or at least started.

    Best regards

    Bjørn 

  • Hi, thanks for the answer. 

    I tried to reply, but the message wasn't posted, so I'll try again.

    We tested the issue on multiple Android devices with versions 7.0, 8.0, 9.0 and had the same issue.

    The sniffer had some issues, but eventually I noticed this packet while updating using the nRF Connect on LG G6:

    Frame 9634: 37 bytes on wire (296 bits), 37 bytes captured (296 bits) on interface 0
    Nordic BLE Sniffer
    Board: 9
    Header, Packet counter: 13367
    Length of packet: 10
    Flags: 0x01
    Channel: 10
    RSSI (dBm): -66
    Event counter: 1
    Delta time (µs end to start): 151
    [Delta time (µs start to start): 383]
    Bluetooth Low Energy Link Layer
    Access Address: 0xaf9abdac
    [Master Address: 61:b2:bc:04:36:02 (61:b2:bc:04:36:02)]
    [Slave Address: ed:50:3a:4f:39:81 (ed:50:3a:4f:39:81)]
    Data Header: 0x0b06
    [L2CAP Index: 472]
    CRC: 0x6737c7
    Bluetooth L2CAP Protocol
    Length: 7
    CID: Attribute Protocol (0x0004)
    Bluetooth Attribute Protocol
    Opcode: Handle Value Indication (0x1d)
    0... .... = Authentication Signature: False
    .0.. .... = Command: False
    ..01 1101 = Method: Handle Value Indication (0x1d)
    Handle: 0x000c (Generic Attribute Profile: Service Changed)
    [Service UUID: Generic Attribute Profile (0x1801)]
    [UUID: Service Changed (0x2a05)]
    Starting Handle: 0x000e
    Ending Handle: 0xffff

    The handles seem fine, but I'm not sure about the rest of it (Authentication? command?).

    Our Android developer tried using the 1600ms delay, but the problem wasn't solved. He's indeed using the latest version from the DFU library.

    Turning Bluetooth off and on solves the issue without even unpairing, so perhaps the indication is ignored until the connection is re-established?

    Thanks

  • I agree that the handles look fine. Do you see the Master acknowledging the indication to the Slave? If you could attach the sniffer trace here then that would be great.  I'll run this by our Android developer and hear what he has to say. 

  • The log itself is unfiltered and filled with empty packets, so I'm attaching the some of the packets that came after the indication. There are still a few "Encrypted packet decrypted incorrectly (bad MIC)" events, so I'm not sure if something was missed.

    In the meanwhile we're exploring the option of unpairing and pairing again automatically, but it's probably not the best solution.

    Service_changed_indication1.pcapng

  • I do not see any acknowledgement of the indication nor any service discovery being performed in the trace. I just see the encryption request from the slave and then the encrypted packets after that, maybe the reply to the indication is in there. 

    However I discussed the issue with our Android developer and if I understood him correctly the issue is not in your application, but in the Android Settings App that handles the HID reports.

    According to him the Android Settings app will see the  new services next time the device connects, which is why why things work after switching Bluetooth off/on.

     Here is what he suggested:

    They could also try to do the same from the peripherals side. After SC indication is sent and Android completes service discovery, their HID device could gracefully disconnect and start advertising directly, so Android should  reconnect quickly or they can restart Bluetooth from the app, but that's ugly (as User may be listening to a music, or something)

    The Settings app asks for services too quickly. It gets them before SC inidcation is received, and has no clue that they have changed. Their app is using correct services, as they waited 1.6 sec before calling gatt.discoverServices().

    He also said that he has contacted Google about this, but he has yet to get a reply. 

    Best regards

    Bjørn 

Related