From 83b9df9df59ca7cc12536b81438690883b87364d Mon Sep 17 00:00:00 2001 From: Ren You Date: Wed, 30 Sep 2020 12:34:05 -0400 Subject: [PATCH] Revert "Use dispatchKeyEventPreIme, and handle keys sent to InputConnection.sendKeyEvent on Android (#21163)" (#21513) This reverts commit 539034ae850d422a5449edcb36c60ad90ac91905. --- .../android/AndroidKeyProcessor.java | 67 ++++++++++--------- .../embedding/android/FlutterView.java | 35 +++++++--- .../editing/InputConnectionAdaptor.java | 15 +---- .../plugin/editing/TextInputPlugin.java | 14 +--- .../android/io/flutter/view/FlutterView.java | 16 ++++- .../android/AndroidKeyProcessorTest.java | 24 +++---- .../editing/InputConnectionAdaptorTest.java | 37 ++++------ 7 files changed, 101 insertions(+), 107 deletions(-) diff --git a/shell/platform/android/io/flutter/embedding/android/AndroidKeyProcessor.java b/shell/platform/android/io/flutter/embedding/android/AndroidKeyProcessor.java index c2c5549596518..14d7effe56c11 100644 --- a/shell/platform/android/io/flutter/embedding/android/AndroidKeyProcessor.java +++ b/shell/platform/android/io/flutter/embedding/android/AndroidKeyProcessor.java @@ -66,8 +66,7 @@ public AndroidKeyProcessor( @NonNull TextInputPlugin textInputPlugin) { this.keyEventChannel = keyEventChannel; this.textInputPlugin = textInputPlugin; - textInputPlugin.setKeyEventProcessor(this); - this.eventResponder = new EventResponder(view, textInputPlugin); + this.eventResponder = new EventResponder(view); this.keyEventChannel.setEventResponseHandler(eventResponder); } @@ -81,33 +80,53 @@ public void destroy() { } /** - * Called when a key event is received by the {@link FlutterView} or the {@link - * InputConnectionAdaptor}. + * Called when a key up event is received by the {@link FlutterView}. * * @param keyEvent the Android key event to respond to. * @return true if the key event should not be propagated to other Android components. Delayed * synthesis events will return false, so that other components may handle them. */ - public boolean onKeyEvent(@NonNull KeyEvent keyEvent) { - int action = keyEvent.getAction(); - if (action != KeyEvent.ACTION_DOWN && action != KeyEvent.ACTION_UP) { - // There is theoretically a KeyEvent.ACTION_MULTIPLE, but that shouldn't - // be sent anymore anyhow. + public boolean onKeyUp(@NonNull KeyEvent keyEvent) { + if (eventResponder.dispatchingKeyEvent) { + // Don't handle it if it is from our own delayed event synthesis. return false; } + + Character complexCharacter = applyCombiningCharacterToBaseCharacter(keyEvent.getUnicodeChar()); + KeyEventChannel.FlutterKeyEvent flutterEvent = + new KeyEventChannel.FlutterKeyEvent(keyEvent, complexCharacter, eventIdSerial++); + keyEventChannel.keyUp(flutterEvent); + eventResponder.addEvent(flutterEvent.eventId, keyEvent); + return true; + } + + /** + * Called when a key down event is received by the {@link FlutterView}. + * + * @param keyEvent the Android key event to respond to. + * @return true if the key event should not be propagated to other Android components. Delayed + * synthesis events will return false, so that other components may handle them. + */ + public boolean onKeyDown(@NonNull KeyEvent keyEvent) { if (eventResponder.dispatchingKeyEvent) { // Don't handle it if it is from our own delayed event synthesis. return false; } + // If the textInputPlugin is still valid and accepting text, then we'll try + // and send the key event to it, assuming that if the event can be sent, + // that it has been handled. + if (textInputPlugin.getLastInputConnection() != null + && textInputPlugin.getInputMethodManager().isAcceptingText()) { + if (textInputPlugin.getLastInputConnection().sendKeyEvent(keyEvent)) { + return true; + } + } + Character complexCharacter = applyCombiningCharacterToBaseCharacter(keyEvent.getUnicodeChar()); KeyEventChannel.FlutterKeyEvent flutterEvent = new KeyEventChannel.FlutterKeyEvent(keyEvent, complexCharacter, eventIdSerial++); - if (action == KeyEvent.ACTION_DOWN) { - keyEventChannel.keyDown(flutterEvent); - } else { - keyEventChannel.keyUp(flutterEvent); - } + keyEventChannel.keyDown(flutterEvent); eventResponder.addEvent(flutterEvent.eventId, keyEvent); return true; } @@ -177,12 +196,10 @@ private static class EventResponder implements KeyEventChannel.EventResponseHand private static final long MAX_PENDING_EVENTS = 1000; final Deque> pendingEvents = new ArrayDeque>(); @NonNull private final View view; - @NonNull private final TextInputPlugin textInputPlugin; boolean dispatchingKeyEvent = false; - public EventResponder(@NonNull View view, @NonNull TextInputPlugin textInputPlugin) { + public EventResponder(@NonNull View view) { this.view = view; - this.textInputPlugin = textInputPlugin; } /** @@ -250,26 +267,12 @@ public void addEvent(long id, @NonNull KeyEvent event) { * @param event the event to be dispatched to the activity. */ public void dispatchKeyEvent(KeyEvent event) { - // If the textInputPlugin is still valid and accepting text, then we'll try - // and send the key event to it, assuming that if the event can be sent, - // that it has been handled. - if (textInputPlugin.getLastInputConnection() != null - && textInputPlugin.getInputMethodManager().isAcceptingText()) { - dispatchingKeyEvent = true; - boolean handled = textInputPlugin.getLastInputConnection().sendKeyEvent(event); - dispatchingKeyEvent = false; - if (handled) { - return; - } - } - // Since the framework didn't handle it, dispatch the key again. if (view != null) { // Turn on dispatchingKeyEvent so that we don't dispatch to ourselves and // send it to the framework again. dispatchingKeyEvent = true; - - view.getRootView().dispatchKeyEventPreIme(event); + view.getRootView().dispatchKeyEvent(event); dispatchingKeyEvent = false; } } diff --git a/shell/platform/android/io/flutter/embedding/android/FlutterView.java b/shell/platform/android/io/flutter/embedding/android/FlutterView.java index 78cc4e7e716d7..48d9243cf86c2 100644 --- a/shell/platform/android/io/flutter/embedding/android/FlutterView.java +++ b/shell/platform/android/io/flutter/embedding/android/FlutterView.java @@ -721,7 +721,27 @@ public boolean checkInputConnectionProxy(View view) { } /** - * Invoked when a hardware key is pressed or released, before the IME receives the key. + * Invoked when key is released. + * + *

This method is typically invoked in response to the release of a physical keyboard key or a + * D-pad button. It is generally not invoked when a virtual software keyboard is used, though a + * software keyboard may choose to invoke this method in some situations. + * + *

{@link KeyEvent}s are sent from Android to Flutter. {@link AndroidKeyProcessor} may do some + * additional work with the given {@link KeyEvent}, e.g., combine this {@code keyCode} with the + * previous {@code keyCode} to generate a unicode combined character. + */ + @Override + public boolean onKeyUp(int keyCode, @NonNull KeyEvent event) { + if (!isAttachedToFlutterEngine()) { + return super.onKeyUp(keyCode, event); + } + + return androidKeyProcessor.onKeyUp(event) || super.onKeyUp(keyCode, event); + } + + /** + * Invoked when key is pressed. * *

This method is typically invoked in response to the press of a physical keyboard key or a * D-pad button. It is generally not invoked when a virtual software keyboard is used, though a @@ -732,13 +752,12 @@ public boolean checkInputConnectionProxy(View view) { * previous {@code keyCode} to generate a unicode combined character. */ @Override - public boolean dispatchKeyEventPreIme(KeyEvent event) { - // If the key processor doesn't handle it, then send it on to the - // superclass. The key processor will typically handle all events except - // those where it has re-dispatched the event after receiving a reply from - // the framework that the framework did not handle it. - return (isAttachedToFlutterEngine() && androidKeyProcessor.onKeyEvent(event)) - || super.dispatchKeyEventPreIme(event); + public boolean onKeyDown(int keyCode, @NonNull KeyEvent event) { + if (!isAttachedToFlutterEngine()) { + return super.onKeyDown(keyCode, event); + } + + return androidKeyProcessor.onKeyDown(event) || super.onKeyDown(keyCode, event); } /** diff --git a/shell/platform/android/io/flutter/plugin/editing/InputConnectionAdaptor.java b/shell/platform/android/io/flutter/plugin/editing/InputConnectionAdaptor.java index 26cb5d9d984e7..d702e2b7855ea 100644 --- a/shell/platform/android/io/flutter/plugin/editing/InputConnectionAdaptor.java +++ b/shell/platform/android/io/flutter/plugin/editing/InputConnectionAdaptor.java @@ -27,7 +27,6 @@ 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; import io.flutter.embedding.engine.systemchannels.TextInputChannel; @@ -35,7 +34,6 @@ class InputConnectionAdaptor extends BaseInputConnection { private final View mFlutterView; private final int mClient; private final TextInputChannel textInputChannel; - private final AndroidKeyProcessor keyProcessor; private final Editable mEditable; private final EditorInfo mEditorInfo; private int mBatchCount; @@ -99,7 +97,6 @@ public InputConnectionAdaptor( View view, int client, TextInputChannel textInputChannel, - AndroidKeyProcessor keyProcessor, Editable editable, EditorInfo editorInfo, FlutterJNI flutterJNI) { @@ -110,7 +107,6 @@ public InputConnectionAdaptor( mEditable = editable; mEditorInfo = editorInfo; mBatchCount = 0; - this.keyProcessor = keyProcessor; this.flutterTextUtils = new FlutterTextUtils(flutterJNI); // We create a dummy Layout with max width so that the selection // shifting acts as if all text were in one line. @@ -132,10 +128,9 @@ public InputConnectionAdaptor( View view, int client, TextInputChannel textInputChannel, - AndroidKeyProcessor keyProcessor, Editable editable, EditorInfo editorInfo) { - this(view, client, textInputChannel, keyProcessor, editable, editorInfo, new FlutterJNI()); + this(view, client, textInputChannel, editable, editorInfo, new FlutterJNI()); } // Send the current state of the editable to Flutter. @@ -328,14 +323,6 @@ private static int clampIndexToEditable(int index, Editable editable) { @Override public boolean sendKeyEvent(KeyEvent event) { - // Give the key processor a chance to process this event. It will send it - // to the framework to be handled and return true. If the framework ends up - // not handling it, the processor will re-send the event, this time - // returning false so that it can be processed here. - if (keyProcessor != null && keyProcessor.onKeyEvent(event)) { - return true; - } - markDirty(); if (event.getAction() == KeyEvent.ACTION_DOWN) { if (event.getKeyCode() == KeyEvent.KEYCODE_DEL) { diff --git a/shell/platform/android/io/flutter/plugin/editing/TextInputPlugin.java b/shell/platform/android/io/flutter/plugin/editing/TextInputPlugin.java index abbece5439490..3090c6fba81fa 100644 --- a/shell/platform/android/io/flutter/plugin/editing/TextInputPlugin.java +++ b/shell/platform/android/io/flutter/plugin/editing/TextInputPlugin.java @@ -33,7 +33,6 @@ import androidx.annotation.Nullable; import androidx.annotation.RequiresApi; import androidx.annotation.VisibleForTesting; -import io.flutter.embedding.android.AndroidKeyProcessor; import io.flutter.embedding.engine.systemchannels.TextInputChannel; import io.flutter.plugin.platform.PlatformViewsController; import java.util.HashMap; @@ -55,7 +54,6 @@ public class TextInputPlugin { @Nullable private Rect lastClientRect; private final boolean restartAlwaysRequired; private ImeSyncDeferringInsetsCallback imeSyncCallback; - private AndroidKeyProcessor keyProcessor; // When true following calls to createInputConnection will return the cached lastInputConnection // if the input @@ -329,15 +327,6 @@ ImeSyncDeferringInsetsCallback getImeSyncCallback() { return imeSyncCallback; } - @NonNull - public AndroidKeyProcessor getKeyEventProcessor() { - return keyProcessor; - } - - public void setKeyEventProcessor(AndroidKeyProcessor processor) { - keyProcessor = processor; - } - /** * Use the current platform view input connection until unlockPlatformViewInputConnection is * called. @@ -480,8 +469,7 @@ public InputConnection createInputConnection(View view, EditorInfo outAttrs) { outAttrs.imeOptions |= enterAction; InputConnectionAdaptor connection = - new InputConnectionAdaptor( - view, inputTarget.id, textInputChannel, keyProcessor, mEditable, outAttrs); + new InputConnectionAdaptor(view, inputTarget.id, textInputChannel, mEditable, outAttrs); outAttrs.initialSelStart = Selection.getSelectionStart(mEditable); outAttrs.initialSelEnd = Selection.getSelectionEnd(mEditable); diff --git a/shell/platform/android/io/flutter/view/FlutterView.java b/shell/platform/android/io/flutter/view/FlutterView.java index 172c4492d665b..9899e1714b255 100644 --- a/shell/platform/android/io/flutter/view/FlutterView.java +++ b/shell/platform/android/io/flutter/view/FlutterView.java @@ -268,9 +268,19 @@ public DartExecutor getDartExecutor() { } @Override - public boolean dispatchKeyEventPreIme(KeyEvent event) { - return (isAttached() && androidKeyProcessor.onKeyEvent(event)) - || super.dispatchKeyEventPreIme(event); + public boolean onKeyUp(int keyCode, KeyEvent event) { + if (!isAttached()) { + return super.onKeyUp(keyCode, event); + } + return androidKeyProcessor.onKeyUp(event) || super.onKeyUp(keyCode, event); + } + + @Override + public boolean onKeyDown(int keyCode, KeyEvent event) { + if (!isAttached()) { + return super.onKeyDown(keyCode, event); + } + return androidKeyProcessor.onKeyDown(event) || super.onKeyDown(keyCode, event); } public FlutterNativeView getFlutterNativeView() { diff --git a/shell/platform/android/test/io/flutter/embedding/android/AndroidKeyProcessorTest.java b/shell/platform/android/test/io/flutter/embedding/android/AndroidKeyProcessorTest.java index 74feb6c804663..8eddb009dc828 100644 --- a/shell/platform/android/test/io/flutter/embedding/android/AndroidKeyProcessorTest.java +++ b/shell/platform/android/test/io/flutter/embedding/android/AndroidKeyProcessorTest.java @@ -51,11 +51,11 @@ public void respondsTrueWhenHandlingNewEvents() { AndroidKeyProcessor processor = new AndroidKeyProcessor(fakeView, fakeKeyEventChannel, mock(TextInputPlugin.class)); - boolean result = processor.onKeyEvent(new FakeKeyEvent(KeyEvent.ACTION_DOWN, 65)); + boolean result = processor.onKeyDown(new FakeKeyEvent(KeyEvent.ACTION_DOWN, 65)); assertEquals(true, result); verify(fakeKeyEventChannel, times(1)).keyDown(any(KeyEventChannel.FlutterKeyEvent.class)); verify(fakeKeyEventChannel, times(0)).keyUp(any(KeyEventChannel.FlutterKeyEvent.class)); - verify(fakeView, times(0)).dispatchKeyEventPreIme(any(KeyEvent.class)); + verify(fakeView, times(0)).dispatchKeyEvent(any(KeyEvent.class)); } @Test @@ -97,31 +97,31 @@ public View answer(InvocationOnMock invocation) throws Throwable { ArgumentCaptor.forClass(KeyEventChannel.FlutterKeyEvent.class); FakeKeyEvent fakeKeyEvent = new FakeKeyEvent(KeyEvent.ACTION_DOWN, 65); - boolean result = processor.onKeyEvent(fakeKeyEvent); + boolean result = processor.onKeyDown(fakeKeyEvent); assertEquals(true, result); // Capture the FlutterKeyEvent so we can find out its event ID to use when // faking our response. verify(fakeKeyEventChannel, times(1)).keyDown(eventCaptor.capture()); boolean[] dispatchResult = {true}; - when(fakeView.dispatchKeyEventPreIme(any(KeyEvent.class))) + when(fakeView.dispatchKeyEvent(any(KeyEvent.class))) .then( new Answer() { @Override public Boolean answer(InvocationOnMock invocation) throws Throwable { KeyEvent event = (KeyEvent) invocation.getArguments()[0]; assertEquals(fakeKeyEvent, event); - dispatchResult[0] = processor.onKeyEvent(event); + dispatchResult[0] = processor.onKeyDown(event); return dispatchResult[0]; } }); // Fake a response from the framework. handlerCaptor.getValue().onKeyEventNotHandled(eventCaptor.getValue().eventId); - verify(fakeView, times(1)).dispatchKeyEventPreIme(fakeKeyEvent); + verify(fakeView, times(1)).dispatchKeyEvent(fakeKeyEvent); assertEquals(false, dispatchResult[0]); verify(fakeKeyEventChannel, times(0)).keyUp(any(KeyEventChannel.FlutterKeyEvent.class)); - verify(fakeRootView, times(1)).dispatchKeyEventPreIme(fakeKeyEvent); + verify(fakeRootView, times(1)).dispatchKeyEvent(fakeKeyEvent); } public void synthesizesEventsWhenKeyUpNotHandled() { @@ -147,31 +147,31 @@ public View answer(InvocationOnMock invocation) throws Throwable { ArgumentCaptor.forClass(KeyEventChannel.FlutterKeyEvent.class); FakeKeyEvent fakeKeyEvent = new FakeKeyEvent(KeyEvent.ACTION_UP, 65); - boolean result = processor.onKeyEvent(fakeKeyEvent); + boolean result = processor.onKeyUp(fakeKeyEvent); assertEquals(true, result); // Capture the FlutterKeyEvent so we can find out its event ID to use when // faking our response. verify(fakeKeyEventChannel, times(1)).keyUp(eventCaptor.capture()); boolean[] dispatchResult = {true}; - when(fakeView.dispatchKeyEventPreIme(any(KeyEvent.class))) + when(fakeView.dispatchKeyEvent(any(KeyEvent.class))) .then( new Answer() { @Override public Boolean answer(InvocationOnMock invocation) throws Throwable { KeyEvent event = (KeyEvent) invocation.getArguments()[0]; assertEquals(fakeKeyEvent, event); - dispatchResult[0] = processor.onKeyEvent(event); + dispatchResult[0] = processor.onKeyUp(event); return dispatchResult[0]; } }); // Fake a response from the framework. handlerCaptor.getValue().onKeyEventNotHandled(eventCaptor.getValue().eventId); - verify(fakeView, times(1)).dispatchKeyEventPreIme(fakeKeyEvent); + verify(fakeView, times(1)).dispatchKeyEvent(fakeKeyEvent); assertEquals(false, dispatchResult[0]); verify(fakeKeyEventChannel, times(0)).keyUp(any(KeyEventChannel.FlutterKeyEvent.class)); - verify(fakeRootView, times(1)).dispatchKeyEventPreIme(fakeKeyEvent); + verify(fakeRootView, times(1)).dispatchKeyEvent(fakeKeyEvent); } @NonNull 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 a2d8eb963a42c..2052a47934c0d 100644 --- a/shell/platform/android/test/io/flutter/plugin/editing/InputConnectionAdaptorTest.java +++ b/shell/platform/android/test/io/flutter/plugin/editing/InputConnectionAdaptorTest.java @@ -25,7 +25,6 @@ import android.view.View; import android.view.inputmethod.EditorInfo; import android.view.inputmethod.ExtractedText; -import io.flutter.embedding.android.AndroidKeyProcessor; import io.flutter.embedding.engine.FlutterJNI; import io.flutter.embedding.engine.dart.DartExecutor; import io.flutter.embedding.engine.systemchannels.TextInputChannel; @@ -69,7 +68,6 @@ public void inputConnectionAdaptor_ReceivesEnter() throws NullPointerException { DartExecutor dartExecutor = spy(new DartExecutor(mockFlutterJni, mock(AssetManager.class))); int inputTargetId = 0; TextInputChannel textInputChannel = new TextInputChannel(dartExecutor); - AndroidKeyProcessor mockKeyProcessor = mock(AndroidKeyProcessor.class); Editable mEditable = Editable.Factory.getInstance().newEditable(""); Editable spyEditable = spy(mEditable); EditorInfo outAttrs = new EditorInfo(); @@ -77,7 +75,7 @@ public void inputConnectionAdaptor_ReceivesEnter() throws NullPointerException { InputConnectionAdaptor inputConnectionAdaptor = new InputConnectionAdaptor( - testView, inputTargetId, textInputChannel, mockKeyProcessor, spyEditable, outAttrs); + testView, inputTargetId, textInputChannel, spyEditable, outAttrs); // Send an enter key and make sure the Editable received it. FakeKeyEvent keyEvent = new FakeKeyEvent(KeyEvent.ACTION_DOWN, KeyEvent.KEYCODE_ENTER); @@ -158,11 +156,10 @@ public void testPerformPrivateCommand_dataIsNull() throws JSONException { FlutterJNI mockFlutterJNI = mock(FlutterJNI.class); DartExecutor dartExecutor = spy(new DartExecutor(mockFlutterJNI, mock(AssetManager.class))); TextInputChannel textInputChannel = new TextInputChannel(dartExecutor); - AndroidKeyProcessor mockKeyProcessor = mock(AndroidKeyProcessor.class); Editable editable = sampleEditable(0, 0); InputConnectionAdaptor adaptor = new InputConnectionAdaptor( - testView, client, textInputChannel, mockKeyProcessor, editable, null, mockFlutterJNI); + testView, client, textInputChannel, editable, null, mockFlutterJNI); adaptor.performPrivateCommand("actionCommand", null); ArgumentCaptor channelCaptor = ArgumentCaptor.forClass(String.class); @@ -186,11 +183,10 @@ public void testPerformPrivateCommand_dataIsByteArray() throws JSONException { FlutterJNI mockFlutterJNI = mock(FlutterJNI.class); DartExecutor dartExecutor = spy(new DartExecutor(mockFlutterJNI, mock(AssetManager.class))); TextInputChannel textInputChannel = new TextInputChannel(dartExecutor); - AndroidKeyProcessor mockKeyProcessor = mock(AndroidKeyProcessor.class); Editable editable = sampleEditable(0, 0); InputConnectionAdaptor adaptor = new InputConnectionAdaptor( - testView, client, textInputChannel, mockKeyProcessor, editable, null, mockFlutterJNI); + testView, client, textInputChannel, editable, null, mockFlutterJNI); Bundle bundle = new Bundle(); byte[] buffer = new byte[] {'a', 'b', 'c', 'd'}; @@ -220,11 +216,10 @@ public void testPerformPrivateCommand_dataIsByte() throws JSONException { FlutterJNI mockFlutterJNI = mock(FlutterJNI.class); DartExecutor dartExecutor = spy(new DartExecutor(mockFlutterJNI, mock(AssetManager.class))); TextInputChannel textInputChannel = new TextInputChannel(dartExecutor); - AndroidKeyProcessor mockKeyProcessor = mock(AndroidKeyProcessor.class); Editable editable = sampleEditable(0, 0); InputConnectionAdaptor adaptor = new InputConnectionAdaptor( - testView, client, textInputChannel, mockKeyProcessor, editable, null, mockFlutterJNI); + testView, client, textInputChannel, editable, null, mockFlutterJNI); Bundle bundle = new Bundle(); byte b = 3; @@ -252,11 +247,10 @@ public void testPerformPrivateCommand_dataIsCharArray() throws JSONException { FlutterJNI mockFlutterJNI = mock(FlutterJNI.class); DartExecutor dartExecutor = spy(new DartExecutor(mockFlutterJNI, mock(AssetManager.class))); TextInputChannel textInputChannel = new TextInputChannel(dartExecutor); - AndroidKeyProcessor mockKeyProcessor = mock(AndroidKeyProcessor.class); Editable editable = sampleEditable(0, 0); InputConnectionAdaptor adaptor = new InputConnectionAdaptor( - testView, client, textInputChannel, mockKeyProcessor, editable, null, mockFlutterJNI); + testView, client, textInputChannel, editable, null, mockFlutterJNI); Bundle bundle = new Bundle(); char[] buffer = new char[] {'a', 'b', 'c', 'd'}; @@ -287,11 +281,10 @@ public void testPerformPrivateCommand_dataIsChar() throws JSONException { FlutterJNI mockFlutterJNI = mock(FlutterJNI.class); DartExecutor dartExecutor = spy(new DartExecutor(mockFlutterJNI, mock(AssetManager.class))); TextInputChannel textInputChannel = new TextInputChannel(dartExecutor); - AndroidKeyProcessor mockKeyProcessor = mock(AndroidKeyProcessor.class); Editable editable = sampleEditable(0, 0); InputConnectionAdaptor adaptor = new InputConnectionAdaptor( - testView, client, textInputChannel, mockKeyProcessor, editable, null, mockFlutterJNI); + testView, client, textInputChannel, editable, null, mockFlutterJNI); Bundle bundle = new Bundle(); char b = 'a'; @@ -319,11 +312,10 @@ public void testPerformPrivateCommand_dataIsCharSequenceArray() throws JSONExcep FlutterJNI mockFlutterJNI = mock(FlutterJNI.class); DartExecutor dartExecutor = spy(new DartExecutor(mockFlutterJNI, mock(AssetManager.class))); TextInputChannel textInputChannel = new TextInputChannel(dartExecutor); - AndroidKeyProcessor mockKeyProcessor = mock(AndroidKeyProcessor.class); Editable editable = sampleEditable(0, 0); InputConnectionAdaptor adaptor = new InputConnectionAdaptor( - testView, client, textInputChannel, mockKeyProcessor, editable, null, mockFlutterJNI); + testView, client, textInputChannel, editable, null, mockFlutterJNI); Bundle bundle = new Bundle(); CharSequence charSequence1 = new StringBuffer("abc"); @@ -355,11 +347,10 @@ public void testPerformPrivateCommand_dataIsCharSequence() throws JSONException FlutterJNI mockFlutterJNI = mock(FlutterJNI.class); DartExecutor dartExecutor = spy(new DartExecutor(mockFlutterJNI, mock(AssetManager.class))); TextInputChannel textInputChannel = new TextInputChannel(dartExecutor); - AndroidKeyProcessor mockKeyProcessor = mock(AndroidKeyProcessor.class); Editable editable = sampleEditable(0, 0); InputConnectionAdaptor adaptor = new InputConnectionAdaptor( - testView, client, textInputChannel, mockKeyProcessor, editable, null, mockFlutterJNI); + testView, client, textInputChannel, editable, null, mockFlutterJNI); Bundle bundle = new Bundle(); CharSequence charSequence = new StringBuffer("abc"); @@ -389,11 +380,10 @@ public void testPerformPrivateCommand_dataIsFloat() throws JSONException { FlutterJNI mockFlutterJNI = mock(FlutterJNI.class); DartExecutor dartExecutor = spy(new DartExecutor(mockFlutterJNI, mock(AssetManager.class))); TextInputChannel textInputChannel = new TextInputChannel(dartExecutor); - AndroidKeyProcessor mockKeyProcessor = mock(AndroidKeyProcessor.class); Editable editable = sampleEditable(0, 0); InputConnectionAdaptor adaptor = new InputConnectionAdaptor( - testView, client, textInputChannel, mockKeyProcessor, editable, null, mockFlutterJNI); + testView, client, textInputChannel, editable, null, mockFlutterJNI); Bundle bundle = new Bundle(); float value = 0.5f; @@ -421,11 +411,10 @@ public void testPerformPrivateCommand_dataIsFloatArray() throws JSONException { FlutterJNI mockFlutterJNI = mock(FlutterJNI.class); DartExecutor dartExecutor = spy(new DartExecutor(mockFlutterJNI, mock(AssetManager.class))); TextInputChannel textInputChannel = new TextInputChannel(dartExecutor); - AndroidKeyProcessor mockKeyProcessor = mock(AndroidKeyProcessor.class); Editable editable = sampleEditable(0, 0); InputConnectionAdaptor adaptor = new InputConnectionAdaptor( - testView, client, textInputChannel, mockKeyProcessor, editable, null, mockFlutterJNI); + testView, client, textInputChannel, editable, null, mockFlutterJNI); Bundle bundle = new Bundle(); float[] value = {0.5f, 0.6f}; @@ -918,7 +907,6 @@ public void inputConnectionAdaptor_RepeatFilter() throws NullPointerException { DartExecutor dartExecutor = spy(new DartExecutor(mockFlutterJni, mock(AssetManager.class))); int inputTargetId = 0; TestTextInputChannel textInputChannel = new TestTextInputChannel(dartExecutor); - AndroidKeyProcessor mockKeyProcessor = mock(AndroidKeyProcessor.class); Editable mEditable = Editable.Factory.getInstance().newEditable(""); Editable spyEditable = spy(mEditable); EditorInfo outAttrs = new EditorInfo(); @@ -926,7 +914,7 @@ public void inputConnectionAdaptor_RepeatFilter() throws NullPointerException { InputConnectionAdaptor inputConnectionAdaptor = new InputConnectionAdaptor( - testView, inputTargetId, textInputChannel, mockKeyProcessor, spyEditable, outAttrs); + testView, inputTargetId, textInputChannel, spyEditable, outAttrs); inputConnectionAdaptor.beginBatchEdit(); assertEquals(textInputChannel.updateEditingStateInvocations, 0); @@ -1171,7 +1159,6 @@ private static InputConnectionAdaptor sampleInputConnectionAdaptor(Editable edit int client = 0; TextInputChannel textInputChannel = mock(TextInputChannel.class); FlutterJNI mockFlutterJNI = mock(FlutterJNI.class); - AndroidKeyProcessor mockKeyProcessor = mock(AndroidKeyProcessor.class); when(mockFlutterJNI.nativeFlutterTextUtilsIsEmoji(anyInt())) .thenAnswer((invocation) -> Emoji.isEmoji((int) invocation.getArguments()[0])); when(mockFlutterJNI.nativeFlutterTextUtilsIsEmojiModifier(anyInt())) @@ -1188,7 +1175,7 @@ private static InputConnectionAdaptor sampleInputConnectionAdaptor(Editable edit .thenAnswer( (invocation) -> Emoji.isRegionalIndicatorSymbol((int) invocation.getArguments()[0])); return new InputConnectionAdaptor( - testView, client, textInputChannel, mockKeyProcessor, editable, null, mockFlutterJNI); + testView, client, textInputChannel, editable, null, mockFlutterJNI); } private class TestTextInputChannel extends TextInputChannel {