Repository: flutter
Issue: Under certain conditions TextInput does not correctly handle backspaces on Android
Labels: a: text input,platform-android,has reproducible steps,P3,team-android,triaged-android,found in release: 3.16,found in release: 3.20

### Steps to reproduce

1. Start up an Android Emulator or device
2. Run the code sample
3. Tap on the green rectangle
4. Type something using the software keyboard
5. Try to delete text

### Expected results

The TextInputClient should have received an updated version of TextEditingValue without the last character.

### Actual results

There is no update.

### Code sample

<details open><summary>Code sample</summary>

```dart
import 'package:flutter/material.dart';
import 'package:flutter/services.dart';

void main() {
  runApp(const MainApp());
}

class MainApp extends StatelessWidget {
  const MainApp({super.key});

  @override
  Widget build(BuildContext context) {
    return const MaterialApp(
      home: Scaffold(
        body: Center(
          child: ColoredBox(
            color: Colors.teal,
            child: _Field(),
          ),
        ),
      ),
    );
  }
}

class _Field extends StatefulWidget {
  const _Field({super.key});

  @override
  State<_Field> createState() => _FieldState();
}

class _FieldState extends State<_Field> {
  final _focusNode = FocusNode();
  final _controller = TextEditingController();

  @override
  void dispose() {
    _focusNode.dispose();
    _controller.dispose();
    super.dispose();
  }

  @override
  Widget build(BuildContext context) {
    return Column(mainAxisSize: MainAxisSize.min, children: [
      MyEditableText(
        focusNode: _focusNode,
        controller: _controller,
      ),
    ]);
  }
}

class MyEditableText extends StatefulWidget {
  final FocusNode focusNode;
  final TextEditingController controller;

  const MyEditableText({
    super.key,
    required this.focusNode,
    required this.controller,
  });

  @override
  State<MyEditableText> createState() => _MyEditableTextState();
}

class _MyEditableTextState extends State<MyEditableText> with TextInputClient {
  static const configuration = TextInputConfiguration(
    autocorrect: false,
    enableDeltaModel: false,
    allowedMimeTypes: [],
    textCapitalization: TextCapitalization.none,
    inputAction: TextInputAction.done,
    autofillConfiguration: AutofillConfiguration.disabled,
    enableInteractiveSelection: false,
    obscureText: false,
    enableSuggestions: false,
    enableIMEPersonalizedLearning: false,
    smartDashesType: SmartDashesType.disabled,
    smartQuotesType: SmartQuotesType.disabled,
  );

  TextInputConnection? _connection;

  @override
  void initState() {
    super.initState();
    widget.focusNode.addListener(_onFocusChanged);
    widget.controller.addListener(_onTextChanged);
  }

  @override
  void didUpdateWidget(covariant MyEditableText oldWidget) {
    super.didUpdateWidget(oldWidget);
    if (oldWidget.focusNode != widget.focusNode) {
      oldWidget.focusNode.removeListener(_onFocusChanged);
      widget.focusNode.addListener(_onFocusChanged);
    }

    if (oldWidget.controller != widget.controller) {
      oldWidget.controller.removeListener(_onTextChanged);
      widget.controller.addListener(_onTextChanged);
      _maybeUpdatePlatform(widget.controller.value);
    }
  }

  @override
  void dispose() {
    widget.focusNode.removeListener(_onFocusChanged);
    widget.controller.removeListener(_onTextChanged);
    _closeConnection();
    super.dispose();
  }

  void _onFocusChanged() {
    if (widget.focusNode.hasFocus) {
      _maybeOpenConnection().show();
    }
  }

  TextInputConnection _maybeOpenConnection() {
    var connection = _connection;
    if (connection != null) return connection;

    connection = _connection = TextInput.attach(this, configuration);

    connection.setEditingState(widget.controller.value);
    return connection;
  }

  void _closeConnection() {
    final connection = _connection;
    if (connection == null) return;

    connection.close();
    _connection = null;
    _currentPlatformValue = null;
  }

  TextEditingValue? _currentPlatformValue;
  void _onTextChanged() {
    _maybeUpdatePlatform(widget.controller.value);
  }

  @override
  void connectionClosed() {
    final connection = _connection;
    if (connection == null) return;

    connection.connectionClosedReceived();
    _connection = null;
    _currentPlatformValue = null;
  }

  @override
  AutofillScope? get currentAutofillScope => null;
  @override
  TextEditingValue? get currentTextEditingValue => widget.controller.value;

  @override
  void performAction(TextInputAction action) {
    widget.focusNode.unfocus();
  }

  @override
  void didChangeInputControl(
      TextInputControl? oldControl, TextInputControl? newControl) {
    super.didChangeInputControl(oldControl, newControl);
    oldControl?.hide();
    newControl?.show();
  }

  @override
  void updateEditingValue(TextEditingValue value) {
    _currentPlatformValue = value;
    widget.controller.value = value;
  }

  void _maybeUpdatePlatform(TextEditingValue value) {
    if (_currentPlatformValue == value) return;

    _currentPlatformValue = value;
    _connection?.setEditingState(value);
  }

  @override
  void performPrivateCommand(String action, Map<String, dynamic> data) {
    assert(false, 'The SplitTextField does not support private commands.');
  }

  @override
  void showAutocorrectionPromptRect(int start, int end) {
    assert(false, 'The SplitTextField does not allow auto corrections.');
  }

  @override
  void updateFloatingCursor(RawFloatingCursorPoint point) {
    assert(false, 'The SplitTextField does not allow selections.');
  }

  void _onTap() {
    if (!widget.focusNode.hasFocus) {
      widget.focusNode.requestFocus();
    } else {
      _maybeOpenConnection().show();
    }
  }

  @override
  Widget build(BuildContext context) {
    return Focus(
      focusNode: widget.focusNode,
      child: GestureDetector(
        behavior: HitTestBehavior.opaque,
        onTap: _onTap,
        child: ListenableBuilder(
          listenable: widget.controller,
          builder: (context, _) {
            return ConstrainedBox(
              constraints: const BoxConstraints(minWidth: 100, minHeight: 100),
              child: Center(
                child: Text(widget.controller.text),
              ),
            );
          },
        ),
      ),
    );
  }
}
```

</details>


### Screenshots or Video

_No response_

### Logs

_No response_

### Flutter Doctor output

<details open><summary>Doctor output</summary>

```console
[✓] Flutter (Channel stable, 3.16.9, on macOS 14.3 23D56 darwin-arm64)
    • Flutter version 3.16.9 on channel stable at /Users/.../Development/flutter
    • Upstream repository https://github.com/flutter/flutter.git
    • Framework revision 41456452f2 (10 days ago), 2024-01-25 10:06:23 -0800
    • Engine revision f40e976bed
    • Dart version 3.2.6
    • DevTools version 2.28.5

[✓] Android toolchain - develop for Android devices (Android SDK version 34.0.0)
    • Android SDK at /Users/.../Library/Android/sdk
    • Platform android-34, build-tools 34.0.0
    • Java binary at: /Applications/Android Studio.app/Contents/jbr/Contents/Home/bin/java
    • Java version OpenJDK Runtime Environment (build 17.0.7+0-17.0.7b1000.6-10550314)
    • All Android licenses accepted.

[✓] Xcode - develop for iOS and macOS (Xcode 15.2)
    • Xcode at /Applications/Xcode.app/Contents/Developer
    • Build 15C500b
    • CocoaPods version 1.15.0

[✓] Chrome - develop for the web
    • Chrome at /Applications/Google Chrome.app/Contents/MacOS/Google Chrome

[✓] Android Studio (version 2023.1)
    • Android Studio at /Applications/Android Studio.app/Contents
    • Flutter plugin can be installed from:
      🔨 https://plugins.jetbrains.com/plugin/9212-flutter
    • Dart plugin can be installed from:
      🔨 https://plugins.jetbrains.com/plugin/6351-dart
    • Java version OpenJDK Runtime Environment (build 17.0.7+0-17.0.7b1000.6-10550314)

[✓] VS Code (version 1.87.0-insider)
    • VS Code at /Applications/Visual Studio Code - Insiders.app/Contents
    • Flutter extension version 3.82.0

[✓] Connected device (2 available)
    • macOS (desktop) • macos  • darwin-arm64   • macOS 14.3 23D56 darwin-arm64
    • Chrome (web)    • chrome • web-javascript • Google Chrome 121.0.6167.139

[✓] Network resources
    • All expected network resources are available.

• No issues found!
```

</details>