Closed angelix closed 9 months ago
Do you have some example for setMaxBatchSize(512 ?
@e-Joe
Example from green_android
@Override public int write(final byte[] bytes) { this.disposable.add(this.connection .flatMap(rxConn -> rxConn.createNewLongWriteBuilder() .setMaxBatchSize(512) .setCharacteristicUuid(IO_TX_CHAR_UUID) .setBytes(bytes) .build()) .subscribe(this::onBytesSent, this::onSendFailure) ); return bytes.length; }
The work-around doesn't work in Android 14, using this .setMaxBatchSize(512) shows no effect for me, any solution for this yet?
@sravan-wellnesys keep in mind that this change is for writing to BLE device. Be sure that the BLE device also respect the spec.
@sravan-wellnesys keep in mind that this change is for writing to BLE device. Be sure that the BLE device also respect the spec.
Can you please explain what exactly needs to be done, as I check this [https://issuetracker.google.com/issues/307234027]( ), Android 14 is by default requesting MTU 517, So should we update our peripheral device to respond to MTU 517 or By doing what you said .setMaxBatchSize(512) and configure our peripheral device to respond to MTU 512 even if Android 14 requests MTU 517?
Btw, this is what I am getting in logs:
packages/modules/Bluetooth/system/stack/gatt/gatt_api.cc:768 GATTC_TryMtuRequest: **:**:**:**:49:fe conn_id=0x000d 2023-12-05 17:54:21.669 15046-15098 bluetooth com.google.android.bluetooth I packages/modules/Bluetooth/system/stack/gatt/gatt_api.cc:728 GATTC_ConfigureMTU: Configuring ATT mtu size conn_id:13 mtu:517 user mtu 512 2023-12-05 17:54:21.684 15046-15098 bluetooth com.google.android.bluetooth I packages/modules/Bluetooth/system/stack/gatt/gatt_cl.cc:1113 gatt_process_mtu_rsp: Local pending MTU 512, Remote (**:**:**:**:49:fe) MTU 517 2023-12-05 17:54:21.684 15046-15098 bluetooth com.google.android.bluetooth I packages/modules/Bluetooth/system/stack/gatt/gatt_cl.cc:1133 gatt_process_mtu_rsp: MTU Exchange resulted in: 517 2023-12-05 17:54:21.684 15046-15098 bt_btm_ble com.google.android.bluetooth I packages/modules/Bluetooth/system/stack/btm/btm_ble.cc:619 BTM_SetBleDataLength: xx:xx:xx:xx:49:fe, 516
[ERROR:gatt_cl.cc(693)] value.len larger than GATT_MAX_ATTR_LEN, discard
Thanks for your time.
Can you please explain what exactly needs to be done, as I check this https://issuetracker.google.com/issues/307234027, Android 14 is by default requesting MTU 517, So should we update our peripheral device to respond to MTU 517 or By doing what you said .setMaxBatchSize(512) and configure our peripheral device to respond to MTU 512 even if Android 14 requests MTU 517?
Your device should respond to MTU request with the value 517, but the actual payload you send must be 512 bytes at maximum.
If the device sends more that 512 bytes, from my experience, Android will silently drop the packet.
On my case i had to firmware update my BLE device to send max 512 bytes, and my Android app to send max 512 bytes.
Explanation: MTU size includes the header size. The header can be from 3-5 bytes, but you should not really care about that. The crucial part is not to send more that 512 byte.
From the issue:
A deeper reason is that the Bluetooth Specification allows the maximum size of an ATT attribute to be 512 bytes and the largest command ATT_PREPARE_WRITE_REQ has 5 bytes of header. Hence 512 + 5 = 517. The packet data itself should never exceed 512 as per the Bluetooth spec.
Can you please explain what exactly needs to be done, as I check this https://issuetracker.google.com/issues/307234027, Android 14 is by default requesting MTU 517, So should we update our peripheral device to respond to MTU 517 or By doing what you said .setMaxBatchSize(512) and configure our peripheral device to respond to MTU 512 even if Android 14 requests MTU 517?
Your device should respond to MTU request with the value 517, but the actual payload you send must be 512 bytes at maximum.
If the device sends more that 512 bytes, from my experience, Android will silently drop the packet.
On my case i had to firmware update my BLE device to send max 512 bytes, and my Android app to send max 512 bytes.
Explanation: MTU size includes the header size. The header can be from 3-5 bytes, but you should not really care about that. The crucial part is not to send more that 512 byte.
From the issue:
A deeper reason is that the Bluetooth Specification allows the maximum size of an ATT attribute to be 512 bytes and the largest command ATT_PREPARE_WRITE_REQ has 5 bytes of header. Hence 512 + 5 = 517. The packet data itself should never exceed 512 as per the Bluetooth spec.
Thanks a lot for your explanation, Is there a way that I don't send a value in requestMTU?, Do Android 14 still request 517 even if I don't specify a size in request instead of the default 23 bytes.
Thanks a lot for your explanation, Is there a way that I don't send a value in requestMTU?, Do Android 14 still request 517 even if I don't specify a size in request instead of the default 23 bytes.
Just don't call requestMTU at all.
From the issue:
requestMTU(23) has the same effect as not calling requestMTU() at all, in that case the default MTU of 23 bytes will be used.
Thanks a lot for your explanation, Is there a way that I don't send a value in requestMTU?, Do Android 14 still request 517 even if I don't specify a size in request instead of the default 23 bytes.
Just don't call requestMTU at all.
From the issue:
requestMTU(23) has the same effect as not calling requestMTU() at all, in that case the default MTU of 23 bytes will be used.
Yep, I am not receiving any bytes, not using requestMTU at all like you said. No data transfer is happening. So firmware upgrade is the only solution at this point? Btw my peripheral device is using Bluetooth 4.2.
Thanks a lot for your explanation, Is there a way that I don't send a value in requestMTU?, Do Android 14 still request 517 even if I don't specify a size in request instead of the default 23 bytes.
Just don't call requestMTU at all. From the issue:
requestMTU(23) has the same effect as not calling requestMTU() at all, in that case the default MTU of 23 bytes will be used.
Yep, I am not receiving any bytes, not using requestMTU at all like you said. No data transfer is happening. So firmware upgrade is the only solution at this point? Btw my peripheral device is using Bluetooth 4.2.
I think so. Try using a different android version and see the size of data the device is sending. If it's more than 512, you can be sure that's your issue.
Thanks a lot for your explanation, Is there a way that I don't send a value in requestMTU?, Do Android 14 still request 517 even if I don't specify a size in request instead of the default 23 bytes.
Just don't call requestMTU at all. From the issue:
requestMTU(23) has the same effect as not calling requestMTU() at all, in that case the default MTU of 23 bytes will be used.
Yep, I am not receiving any bytes, not using requestMTU at all like you said. No data transfer is happening. So firmware upgrade is the only solution at this point? Btw my peripheral device is using Bluetooth 4.2.
I think so. Try using a different android version and see the size of data the device is sending. If it's more than 512, you can be sure that's your issue.
I tried with Android 12, When Mtu - 512, I get 509 bytes, when Mtu size - 517, I receive 514 bytes, I thought the max was 512. So app issue or device issue?
I think is device issue that needs a fix with firmware update, the device should not send more than 512 bytes.
I think is device issue that needs a fix with firmware update, the device should not send more than 512 bytes.
So anything more than 512 does not work for Android 14, but works for the previous versions?
So anything more than 512 does not work for Android 14, but works for the previous versions?
Correct, Android 14 is more strict following more strictly the version 5.2 of the Bluetooth Core.
This is a problem that the library can fix on its side — that is fix the LongWriteOperation (which btw. does not use Prepared Write but chunks data on the application side) to send maximum of 512 bytes of data on Android 13 and above. That way people will not get caught by surprise when using LongWriteOperationBuilder's default chunk size. WDYT?
Android 14 introduced a breaking change related to MTU negotiation.
This breaking change it may even require a firmware upgrade on the device to properly support the BLE spec in a more strict way.
On the library side, if you try to write more than 512 bytes using the
LongWriteOperationBuilder
, the write fails silently.By default the following method is used to calculate the batch size.
On Android 14 the call to
rxBleConnection.getMtu()
returns 517. 517 - 3 (GATT_WRITE_MTU_OVERHEAD) = 514 which is larger than the accepted 512.Based on this very informative issue ticket MTU Overhead should be 5.
As a work around you can use
setMaxBatchSize(512)
when creating theLongWriteOperationBuilder
to use theConstantPayloadSizeLimit
implementation instead of the defaultMtuBasedPayloadSizeLimit
.