Android Ble library MTU change on peripheral

Hello,

I have some troubles understanding the design of the MTU exchange within the Android Nordic Library. 

We are using a NRF52840 SDK 17 softdevice version 7.2.0 and a mobile application which integrated the Android Nordic Library version 2.6.0. 

In the Nordic SDK of the nrf52840, in module nrf_ble_gatt.c the function on_connected_evt will react to the connection and if the macro NRF_BLE_GATT_MTU_EXCHANGE_INITIATION_ENABLED is set, it will automatically make a call to the softdevice to make a mtu request to the peer. Which is visible from the Android logs as well as from the sniffer traces... 

But then in the Android BLE Nordic library the internal MTU is not changed and if we want to perform some GATT write operation on the server on the nrf board the packets are splitted in small chunks which take the default MTU ( 23 )...   

Then from the documentation inside the Nordic android library, it's then clear that if the MTU request is not issued by the central, the mtu is not the correct one as it's written in the documentation : 

/**
* Returns the current MTU (Maximum Transfer Unit). MTU specifies the maximum number of bytes
* that can be sent in a single write operation. 3 bytes are used for internal purposes,
* so the maximum size is MTU-3. The value will changed only if requested with
* {@link #requestMtu(int)} and a successful callback is received. If the peripheral requests
* MTU change, the {@link BluetoothGattCallback#onMtuChanged(BluetoothGatt, int, int)}
* callback is not invoked, therefor the returned MTU value will not be correct.
* Use {@link android.bluetooth.BluetoothGattServerCallback#onMtuChanged(BluetoothDevice, int)}
* to get the callback with right value requested from the peripheral side.
*
* @return the current MTU value. Default to 23.
*/
@IntRange(from = 23, to = 517)
protected int getMtu() {
return requestHandler.getMtu();
}

So here I'm just wondering why it has been designed that way and why the mtu as requested by the peripheral is not taken into account ?  The 2 software components ( nrf52840 sdk and the Android library ) seem not that interoperable in that specific matter.

Thank you for your help. 

Parents
  • Hi Jean-Baptiste,

    I am asking our app team regarding your question about the design decision around the tracking of the MTU value. Looks to me that the API expects you to call overrideMtu() on the relevant MTU callbacks.

    Meanwhile, I would like to check if MTU negotiation was actually successful between the devices.

    What are the logs on both the Android side and the nRF52840 side concerning the MTU exchange? Is the result reflected in your sniffer trace?

    On the nRF52840 device, if your application is using the nrf_ble_gatt library, you can enable log level debug for that library and see the result of the negotiation.
    If the application is handling the negotiation on its own, then you can log the event data of the SoftDevice event BLE_GATTS_EVT_EXCHANGE_MTU_REQUEST.

    Hieu

  • Hi Hieu,

    thank you for your answer, 

    the MTU request and update is reflected in both logs of the app and the  nrf : 

    RTT traces :

    ...
    00> [12:00:37] <debug> nrf_ble_gatt: Requesting to update ATT MTU to 245 bytes on connection 0x0.
    00> [12:00:37] <debug> nrf_ble_gatt: Updating data length to 249 on connection 0x0.

    ...
    00> [12:00:38] <debug> nrf_ble_gatt: ATT MTU updated to 245 bytes on connection 0x0 (response).
    00> [12:00:38] <info> BLE: The ATT_MTU size was updated to 245 bytes.
    ...

    APP log : 

    Sniffer :

    Then from the sniffer trace, we can observe that the transaction from the nrf to the app ( indications or notifications ) use correctly the new MTU, but the app using the nordic android library still considers that the mtu has not changed and continue splitting the long packets in small chunks. 

  • Hi Jean Baptiste,

    I see, it looks like the MTU negotiation was indeed successful.

    To have the MTU value updated correctly within a BleManager, you have two approaches:

    1. If you setup a BleServerManager, the BleServerManager will receive the necessary callback and update the MTU value automatically for you.
      Here is an example for BleServerManager initialization: link.
      The BleServerManager must also be added to each BleManager instance; refer to: link.

    2. In your android.bluetooth.BluetoothGattServerCallback#onMtuChanged(), you must call BleManager#overrideMtu().

    Please try one of the two options and let me know if it helps you.

Reply
  • Hi Jean Baptiste,

    I see, it looks like the MTU negotiation was indeed successful.

    To have the MTU value updated correctly within a BleManager, you have two approaches:

    1. If you setup a BleServerManager, the BleServerManager will receive the necessary callback and update the MTU value automatically for you.
      Here is an example for BleServerManager initialization: link.
      The BleServerManager must also be added to each BleManager instance; refer to: link.

    2. In your android.bluetooth.BluetoothGattServerCallback#onMtuChanged(), you must call BleManager#overrideMtu().

    Please try one of the two options and let me know if it helps you.

Children
No Data
Related