Skip to content

Conversation

@krushnarout
Copy link
Member

Android processes only one ble write at once, that’s why it was crashing

fix: added sequential queue, timeout, and busy error handling

closes #3440

Copy link
Contributor

@gemini-code-assist gemini-code-assist bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Code Review

This pull request introduces a sequential write queue with retry logic to handle BLE write limitations on Android. The implementation correctly serializes write operations and adds robustness with timeouts and exponential backoff for retries. My review includes one suggestion to improve the robustness of the error-checking logic for retries, to avoid potential false positives from a broad string match.

bool _isRetryable(Object e) {
if (e is FlutterBluePlusException && e.code == 201) return true;
final msg = e.toString().toLowerCase();
return msg.contains("busy") || msg.contains("201");
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

high

The string check msg.contains("201") is a bit fragile and could lead to incorrectly retrying on errors that are not retryable. For example, it could match parts of other numbers in an error message (e.g., a different error code like 1201, or part of a memory address). To make this more robust, consider using a more specific pattern, for example by checking for word boundaries.

Suggested change
return msg.contains("busy") || msg.contains("201");
return msg.contains("busy") || RegExp(r'\b201\b').hasMatch(msg);

@aaravgarg aaravgarg requested a review from beastoin November 21, 2025 06:13
@beastoin
Copy link
Collaborator

where are the tests sir ?

@krushnarout

@krushnarout
Copy link
Member Author

before:

when I try to set the mic gain and dimming frequently

logs:

BLE Transport: Failed to write characteristic: PlatformException(writeCharacteristic, gatt writeCharacteristic() returned 201 : ERROR_GATT_WRITE_REQUEST_BUSY, null, null) 
OmiDeviceConnection: Error setting LED dim ratio: PlatformException(writeCharacteristic, gatt.writeCharacteristic() returned 201 : ERROR_GATT_WRITE_REQUEST_BUSY, null, null)
writeCharacteristic() - prior command is not finished, mClient= 6
Screen.Recording.2025-11-23.at.3.25.22.PM.mov

added two debug prints in ble_transport.dart

Screenshot 2025-11-23 at 3 58 23 PM

after:

here it handling properly

Screen.Recording.2025-11-23.at.9.26.50.PM.mov

@beastoin

@krushnarout
Copy link
Member Author

I found another error, if I try to set the mic gain while the device is disconnected (either out of range or manually turned off)

log:

OmiDeviceConnection: Error setting mic gain: FlutterBluePlusException | writeCharacteristic | android-code: 133 | GATT_ERROR
BLE write attempt #1 to 19b10010-e8f2-537e-4f6c-d104768a1214:19b10012-e8f2-537e-4f6c-d104768a1214 len=1
OmiDeviceConnection: Error setting mic gain: PlatformException(writeCharacteristic, gatt writeCharacteristic() returned 4 : UNKNOWN_BLE_ERROR (4), null, null)

before:

Screenshot 2025-11-23 at 2 32 41 PM

after:

fix: If the device disconnects, all writes stop instantly

Screen.Recording.2025-11-23.at.11.59.08.PM.mov

@aaravgarg
Copy link
Collaborator

@beastoin pls review, thanks!

@beastoin
Copy link
Collaborator

1/ don't update the state on the writing; whatever the error is, it's not the write func's responsibility.

2/ why do we need to put the writewithoutresponse here https://github.com/BasedHardware/omi/pull/3471/files#diff-9642bdfe5ce0f1472db61c4f7cb153a7b340385781f777a1d674a649eb824333R203-R204?

@krushnarout
Copy link
Member Author

1/ don't update the state on the writing; whatever the error is, it's not the write func's responsibility.

removed

2/ why do we need to put the writewithoutresponse here https://github.com/BasedHardware/omi/pull/3471/files#diff-9642bdfe5ce0f1472db61c4f7cb153a7b340385781f777a1d674a649eb824333R203-R204?

It will choose the fastest supported write mode for the characteristic, when the device allows it for better performance and falling back to normal writes when required. writeWithoutResponse is faster because it avoids waiting

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

FlutterError - PlatformException(writeCharacteristic, device is disconnected, null, null)

4 participants