Repository: flutter
Issue: IME deltas on Android trigger input method restarts when they shouldn't
Labels: a: text input,platform-android,P2,team-framework,triaged-framework

I'm integrating the relatively new IME deltas in Flutter into a document editor. I'm finding that on Android (not iOS), that it's essentially impossible to keep Android from restarting the input method due to changes to the composing region.

For example, I have a blob of text. I place the caret in the text. Then I press and hold the backspace button on the Android software keyboard. The expected behavior is that delete deltas keep getting reported until all the available text is gone. In reality, at random times, the Flutter Android embedding decides that it doesn't like the composing region and forces the input method to restart. This abruptly causes the deletion to stop.

The deletion problem is exceptionally visible when you place the caret at the very end of the text. In that case, the deletion only makes it 1 character before the input method restarts. This essentially means that if a user wants to delete a bunch of text, including the last character in the text, then that user needs to press the backspace button for every single character.

The offending code in the Android embedding is here:
https://github.com/flutter/engine/blob/main/shell/platform/android/io/flutter/plugin/editing/TextInputPlugin.java#L469

To mitigate this problem, I've tried to send composing regions to the OS that match what the OS wants. Unfortunately, mismatches still show up. At this moment, I don't even care about composing regions. The OS can do whatever it wants with composing regions. But I need the input method to stop restarting itself.

You'll know that this issue is triggered when the following appears in your run output:
```
I/TextInputPlugin( 8040): Composing region changed by the framework. Restarting the input method.
W/IInputConnectionWrapper( 8040): beginBatchEdit on inactive InputConnection
W/IInputConnectionWrapper( 8040): getTextBeforeCursor on inactive InputConnection
W/IInputConnectionWrapper( 8040): getTextAfterCursor on inactive InputConnection
W/IInputConnectionWrapper( 8040): getSelectedText on inactive InputConnection
W/IInputConnectionWrapper( 8040): endBatchEdit on inactive InputConnection
W/IInputConnectionWrapper( 8040): beginBatchEdit on inactive InputConnection
W/IInputConnectionWrapper( 8040): endBatchEdit on inactive InputConnection
W/IInputConnectionWrapper( 8040): beginBatchEdit on inactive InputConnection
W/IInputConnectionWrapper( 8040): endBatchEdit on inactive InputConnection

```

**Reproduction code:** I know the team wants a minimal reproduction, but each time that I file one of the IME delta issues it's putting me in a position where I have to copy/paste an entire `TextInputClient` implementation. I don't think that's a good use of my time. If someone on the team can demonstrate text input and deletion using IME deltas without running into this problem, I'd like to see it.

Flutter version:
```
Flutter 2.10.0 • channel stable • https://github.com/flutter/flutter.git
Framework • revision 5f105a6ca7 (2 days ago) • 2022-02-01 14:15:42 -0800
Engine • revision 776efd2034
Tools • Dart 2.16.0 • DevTools 2.9.2
```