[flutter_releases] Flutter Stable 2.2.3 Engine Cherrypicks (#27081)

* 'Update Dart SDK to 065872e802209ffa97aa3fad204758830b6100a0'
* [Android TextInput] clean up nested batch edits in closeConnection() (#26628)
* update gcloud credentials (#26868)

Co-authored-by: LongCatIsLooong <31859944+LongCatIsLooong@users.noreply.github.com>
Co-authored-by: keyonghan <54558023+keyonghan@users.noreply.github.com>
diff --git a/.cirrus.yml b/.cirrus.yml
index ca1d651..75ec95d 100644
--- a/.cirrus.yml
+++ b/.cirrus.yml
@@ -1,4 +1,4 @@
-gcp_credentials: ENCRYPTED[a4b6c1cb428a657573b775d39dd8006beed3013d01ca3d1a3972bdc2bd39bb937dd91ea3d98eeb9ce55e4bd303d045d3]
+gcp_credentials: ENCRYPTED[!0e63b52bd7e4fda1cd7b7bf2b4fe515a27fadbeaced01f5ad8b699b81d3611ed64c5d3271bcd8426dd914ef41cba48a0!]
 
 # LINUX
 task:
diff --git a/DEPS b/DEPS
index f066566..ca210b9 100644
--- a/DEPS
+++ b/DEPS
@@ -35,7 +35,7 @@
   # Dart is: https://github.com/dart-lang/sdk/blob/master/DEPS.
   # You can use //tools/dart/create_updated_flutter_deps.py to produce
   # updated revision list of existing dependencies.
-  'dart_revision': '516eb3b05c252ef3d34255d06700c1f09f7f4502',
+  'dart_revision': '065872e802209ffa97aa3fad204758830b6100a0',
 
   # WARNING: DO NOT EDIT MANUALLY
   # The lines between blank lines above and below are generated by a script. See create_updated_flutter_deps.py
diff --git a/shell/platform/android/io/flutter/plugin/editing/InputConnectionAdaptor.java b/shell/platform/android/io/flutter/plugin/editing/InputConnectionAdaptor.java
index 0b68c27..843b24e 100644
--- a/shell/platform/android/io/flutter/plugin/editing/InputConnectionAdaptor.java
+++ b/shell/platform/android/io/flutter/plugin/editing/InputConnectionAdaptor.java
@@ -4,13 +4,11 @@
 
 package io.flutter.plugin.editing;
 
-import android.annotation.SuppressLint;
 import android.content.ClipData;
 import android.content.ClipboardManager;
 import android.content.Context;
 import android.os.Build;
 import android.os.Bundle;
-import android.provider.Settings;
 import android.text.DynamicLayout;
 import android.text.Editable;
 import android.text.InputType;
@@ -25,7 +23,6 @@
 import android.view.inputmethod.ExtractedText;
 import android.view.inputmethod.ExtractedTextRequest;
 import android.view.inputmethod.InputMethodManager;
-import android.view.inputmethod.InputMethodSubtype;
 import io.flutter.Log;
 import io.flutter.embedding.android.AndroidKeyProcessor;
 import io.flutter.embedding.engine.FlutterJNI;
@@ -48,6 +45,8 @@
   private InputMethodManager mImm;
   private final Layout mLayout;
   private FlutterTextUtils flutterTextUtils;
+  private final KeyboardManager keyboardManager;
+  private int batchEditNestDepth = 0;
 
   @SuppressWarnings("deprecation")
   public InputConnectionAdaptor(
@@ -135,12 +134,14 @@
   @Override
   public boolean beginBatchEdit() {
     mEditable.beginBatchEdit();
+    batchEditNestDepth += 1;
     return super.beginBatchEdit();
   }
 
   @Override
   public boolean endBatchEdit() {
     boolean result = super.endBatchEdit();
+    batchEditNestDepth -= 1;
     mEditable.endBatchEdit();
     return result;
   }
@@ -238,27 +239,9 @@
   public void closeConnection() {
     super.closeConnection();
     mEditable.removeEditingStateListener(this);
-  }
-
-  // Detect if the keyboard is a Samsung keyboard, where we apply Samsung-specific hacks to
-  // fix critical bugs that make the keyboard otherwise unusable. See finishComposingText() for
-  // more details.
-  @SuppressLint("NewApi") // New API guard is inline, the linter can't see it.
-  @SuppressWarnings("deprecation")
-  private boolean isSamsung() {
-    InputMethodSubtype subtype = mImm.getCurrentInputMethodSubtype();
-    // Impacted devices all shipped with Android Lollipop or newer.
-    if (subtype == null
-        || Build.VERSION.SDK_INT < Build.VERSION_CODES.LOLLIPOP
-        || !Build.MANUFACTURER.equals("samsung")) {
-      return false;
+    for (; batchEditNestDepth > 0; batchEditNestDepth--) {
+      endBatchEdit();
     }
-    String keyboardName =
-        Settings.Secure.getString(
-            mFlutterView.getContext().getContentResolver(), Settings.Secure.DEFAULT_INPUT_METHOD);
-    // The Samsung keyboard is called "com.sec.android.inputmethod/.SamsungKeypad" but look
-    // for "Samsung" just in case Samsung changes the name of the keyboard.
-    return keyboardName.contains("Samsung");
   }
 
   @Override
diff --git a/shell/platform/android/io/flutter/plugin/editing/TextInputPlugin.java b/shell/platform/android/io/flutter/plugin/editing/TextInputPlugin.java
index b59f8e3..e35578f 100644
--- a/shell/platform/android/io/flutter/plugin/editing/TextInputPlugin.java
+++ b/shell/platform/android/io/flutter/plugin/editing/TextInputPlugin.java
@@ -441,9 +441,7 @@
       // to reset their internal states.
       mRestartInputPending = composingChanged(mLastKnownFrameworkTextEditingState, state);
       if (mRestartInputPending) {
-        Log.w(
-            TAG,
-            "Changing the content within the the composing region may cause the input method to behave strangely, and is therefore discouraged. See https://github.com/flutter/flutter/issues/78827 for more details");
+        Log.i(TAG, "Composing region changed by the framework. Restarting the input method.");
       }
     }
 
diff --git a/shell/platform/android/test/io/flutter/plugin/editing/InputConnectionAdaptorTest.java b/shell/platform/android/test/io/flutter/plugin/editing/InputConnectionAdaptorTest.java
index a0f98f9..d90e342 100644
--- a/shell/platform/android/test/io/flutter/plugin/editing/InputConnectionAdaptorTest.java
+++ b/shell/platform/android/test/io/flutter/plugin/editing/InputConnectionAdaptorTest.java
@@ -1115,6 +1115,19 @@
     assertFalse(didConsume);
   }
 
+  @Test
+  public void testCleanUpBatchEndsOnCloseConnection() {
+    final ListenableEditingState editable = sampleEditable(0, 0);
+    InputConnectionAdaptor adaptor = spy(sampleInputConnectionAdaptor(editable));
+    for (int i = 0; i < 5; i++) {
+      adaptor.beginBatchEdit();
+    }
+    adaptor.endBatchEdit();
+    verify(adaptor, times(1)).endBatchEdit();
+    adaptor.closeConnection();
+    verify(adaptor, times(4)).endBatchEdit();
+  }
+
   private static final String SAMPLE_TEXT =
       "Lorem ipsum dolor sit amet," + "\nconsectetur adipiscing elit.";