From 7eec13b458d07c0ec06cd9435156f97ffe76ff9c Mon Sep 17 00:00:00 2001 From: Yohei Yukawa Date: Fri, 30 Jul 2021 09:07:36 -0700 Subject: [PATCH] Revert "A unified data class to represent all the InputConnection call" This reverts commit 2757c248807006916a794d38d455670e48dabcd2 [1]. Reason for revert: We will try another approach to implement InputConnection task cancellation without InputConnectionCommand. [1]: I86eba7185b4b0664c1b0b3da794dfc5eeddc725c Bug: 194151409 Change-Id: I0ef1e1b498b77caf7704742d88c7c81944d75c42 Test: atest CtsInputMethodTestCases:InputConnectionEndToEndTest --- .../internal/inputmethod/CallbackUtils.java | 143 ----- .../inputmethod/IInputContextInvoker.java | 478 ++-------------- .../inputmethod/InputConnectionCommand.aidl | 19 - .../inputmethod/InputConnectionCommand.java | 460 --------------- .../InputConnectionCommandType.java | 84 --- .../inputmethod/InputMethodDebug.java | 128 ----- .../view/IInputConnectionWrapper.java | 536 ++++++++++++------ .../android/internal/view/IInputContext.aidl | 69 ++- .../inputmethod/InputMethodDebugTest.java | 9 - 9 files changed, 487 insertions(+), 1439 deletions(-) delete mode 100644 core/java/com/android/internal/inputmethod/InputConnectionCommand.aidl delete mode 100644 core/java/com/android/internal/inputmethod/InputConnectionCommand.java delete mode 100644 core/java/com/android/internal/inputmethod/InputConnectionCommandType.java diff --git a/core/java/com/android/internal/inputmethod/CallbackUtils.java b/core/java/com/android/internal/inputmethod/CallbackUtils.java index 2b9556d103cd8..aca761de54d46 100644 --- a/core/java/com/android/internal/inputmethod/CallbackUtils.java +++ b/core/java/com/android/internal/inputmethod/CallbackUtils.java @@ -17,11 +17,7 @@ package com.android.internal.inputmethod; import android.annotation.NonNull; -import android.annotation.Nullable; import android.os.RemoteException; -import android.util.Log; -import android.view.inputmethod.ExtractedText; -import android.view.inputmethod.SurroundingText; import java.util.function.BooleanSupplier; import java.util.function.IntSupplier; @@ -141,143 +137,4 @@ public final class CallbackUtils { callback.onResult(result); } catch (RemoteException ignored) { } } - - /** - * A utility method to reply associated with {@link InputConnectionCommand}. - * - * @param command {@link InputConnectionCommand} to be replied. - * @param result a {@link String} value to be replied. - * @param tag tag name to be used for debug output when the invocation fails. - */ - public static void onResult(@NonNull InputConnectionCommand command, boolean result, - @Nullable String tag) { - if (command.mResultCallbackType != InputConnectionCommand.ResultCallbackType.BOOLEAN) { - if (tag != null) { - Log.e(tag, InputMethodDebug.inputConnectionCommandTypeToString(command.mCommandType) - + ": Failed to return result=" + result + " due to callback type mismatch." - + " expected=String actual=" + command.mResultCallbackType); - } - return; - } - try { - IBooleanResultCallback.Stub.asInterface(command.mResultCallback).onResult(result); - } catch (Throwable e) { - if (tag != null) { - Log.e(tag, InputMethodDebug.inputConnectionCommandTypeToString(command.mCommandType) - + ": Failed to return result=" + result, e); - } - } - } - - /** - * A utility method to reply associated with {@link InputConnectionCommand}. - * - * @param command {@link InputConnectionCommand} to be replied. - * @param result an int result value to be replied. - * @param tag tag name to be used for debug output when the invocation fails. - */ - public static void onResult(@NonNull InputConnectionCommand command, int result, - @Nullable String tag) { - if (command.mResultCallbackType != InputConnectionCommand.ResultCallbackType.INT) { - if (tag != null) { - Log.e(tag, InputMethodDebug.inputConnectionCommandTypeToString(command.mCommandType) - + ": Failed to return result=" + result + " due to callback type mismatch." - + " expected=int actual=" + command.mResultCallbackType); - } - return; - } - try { - IIntResultCallback.Stub.asInterface(command.mResultCallback).onResult(result); - } catch (Throwable e) { - if (tag != null) { - Log.e(tag, InputMethodDebug.inputConnectionCommandTypeToString(command.mCommandType) - + ": Failed to return result=" + result, e); - } - } - } - - /** - * A utility method to reply associated with {@link InputConnectionCommand}. - * - * @param command {@link InputConnectionCommand} to be replied. - * @param result a {@link CharSequence} result value to be replied. - * @param tag tag name to be used for debug output when the invocation fails. - */ - public static void onResult(@NonNull InputConnectionCommand command, - @Nullable CharSequence result, @Nullable String tag) { - if (command.mResultCallbackType - != InputConnectionCommand.ResultCallbackType.CHAR_SEQUENCE) { - if (tag != null) { - Log.e(tag, InputMethodDebug.inputConnectionCommandTypeToString(command.mCommandType) - + ": Failed to return result=" + result + " due to callback type mismatch." - + " expected=CharSequence actual=" + command.mResultCallbackType); - } - return; - } - try { - ICharSequenceResultCallback.Stub.asInterface(command.mResultCallback).onResult(result); - } catch (Throwable e) { - if (tag != null) { - Log.e(tag, InputMethodDebug.inputConnectionCommandTypeToString(command.mCommandType) - + ": Failed to return result=" + result, e); - } - } - } - - /** - * A utility method to reply associated with {@link InputConnectionCommand}. - * - * @param command {@link InputConnectionCommand} to be replied. - * @param result a {@link ExtractedText} result value to be replied. - * @param tag tag name to be used for debug output when the invocation fails. - */ - public static void onResult(@NonNull InputConnectionCommand command, - @Nullable ExtractedText result, @Nullable String tag) { - if (command.mResultCallbackType - != InputConnectionCommand.ResultCallbackType.EXTRACTED_TEXT) { - if (tag != null) { - Log.e(tag, InputMethodDebug.inputConnectionCommandTypeToString(command.mCommandType) - + ": Failed to return result=" + result + " due to callback type mismatch." - + " expected=ExtractedText actual=" + command.mResultCallbackType); - } - return; - } - try { - IExtractedTextResultCallback.Stub.asInterface(command.mResultCallback).onResult(result); - } catch (Throwable e) { - if (tag != null) { - Log.e(tag, InputMethodDebug.inputConnectionCommandTypeToString(command.mCommandType) - + ": Failed to return result=" + result, e); - } - } - } - - /** - * A utility method to reply associated with {@link InputConnectionCommand}. - * - * @param command {@link InputConnectionCommand} to be replied. - * @param result a {@link SurroundingText} result value to be replied. - * @param tag tag name to be used for debug output when the invocation fails. - */ - public static void onResult(@NonNull InputConnectionCommand command, - @Nullable SurroundingText result, @Nullable String tag) { - if (command.mResultCallbackType - != InputConnectionCommand.ResultCallbackType.SURROUNDING_TEXT) { - if (tag != null) { - Log.e(tag, InputMethodDebug.inputConnectionCommandTypeToString(command.mCommandType) - + ": Failed to return result=" + result + " due to callback type mismatch." - + " expected=SurroundingText actual=" + command.mResultCallbackType); - } - return; - } - try { - ISurroundingTextResultCallback.Stub.asInterface(command.mResultCallback) - .onResult(result); - } catch (Throwable e) { - if (tag != null) { - Log.e(tag, InputMethodDebug.inputConnectionCommandTypeToString(command.mCommandType) - + ": Failed to return result=" + result, e); - } - } - } } diff --git a/core/java/com/android/internal/inputmethod/IInputContextInvoker.java b/core/java/com/android/internal/inputmethod/IInputContextInvoker.java index 7a43a55040a53..977f9a5a51105 100644 --- a/core/java/com/android/internal/inputmethod/IInputContextInvoker.java +++ b/core/java/com/android/internal/inputmethod/IInputContextInvoker.java @@ -18,7 +18,6 @@ package com.android.internal.inputmethod; import android.annotation.AnyThread; import android.annotation.NonNull; -import android.annotation.Nullable; import android.os.Bundle; import android.os.RemoteException; import android.view.KeyEvent; @@ -33,7 +32,7 @@ import java.util.Objects; /** * A stateless wrapper of {@link com.android.internal.view.IInputContext} to encapsulate boilerplate - * code around {@link InputConnectionCommand}, {@link Completable} and {@link RemoteException}. + * code around {@link Completable} and {@link RemoteException}. */ public final class IInputContextInvoker { @@ -56,7 +55,8 @@ public final class IInputContextInvoker { } /** - * Implements {@link android.view.inputmethod.InputConnection#getTextAfterCursor(int, int)}. + * Invokes {@link IInputContext#getTextAfterCursor(int, int, + * com.android.internal.inputmethod.ICharSequenceResultCallback)}. * * @param length {@code length} parameter to be passed. * @param flags {@code flags} parameter to be passed. @@ -67,9 +67,8 @@ public final class IInputContextInvoker { @NonNull public Completable.CharSequence getTextAfterCursor(int length, int flags) { final Completable.CharSequence value = Completable.createCharSequence(); - final InputConnectionCommand command = Commands.getTextAfterCursor(length, flags, value); try { - mIInputContext.doEdit(command); + mIInputContext.getTextAfterCursor(length, flags, ResultCallbacks.of(value)); } catch (RemoteException e) { value.onError(ThrowableHolder.of(e)); } @@ -77,7 +76,7 @@ public final class IInputContextInvoker { } /** - * Implements {@link android.view.inputmethod.InputConnection#getTextBeforeCursor(int, int)}. + * Invokes {@link IInputContext#getTextBeforeCursor(int, int, ICharSequenceResultCallback)}. * * @param length {@code length} parameter to be passed. * @param flags {@code flags} parameter to be passed. @@ -88,9 +87,8 @@ public final class IInputContextInvoker { @NonNull public Completable.CharSequence getTextBeforeCursor(int length, int flags) { final Completable.CharSequence value = Completable.createCharSequence(); - final InputConnectionCommand command = Commands.getTextBeforeCursor(length, flags, value); try { - mIInputContext.doEdit(command); + mIInputContext.getTextBeforeCursor(length, flags, ResultCallbacks.of(value)); } catch (RemoteException e) { value.onError(ThrowableHolder.of(e)); } @@ -98,7 +96,7 @@ public final class IInputContextInvoker { } /** - * Implements {@link android.view.inputmethod.InputConnection#getSelectedText(int)}. + * Invokes {@link IInputContext#getSelectedText(int, ICharSequenceResultCallback)}. * * @param flags {@code flags} parameter to be passed. * @return {@link Completable.CharSequence} that can be used to retrieve the invocation result. @@ -108,9 +106,8 @@ public final class IInputContextInvoker { @NonNull public Completable.CharSequence getSelectedText(int flags) { final Completable.CharSequence value = Completable.createCharSequence(); - final InputConnectionCommand command = Commands.getSelectedText(flags, value); try { - mIInputContext.doEdit(command); + mIInputContext.getSelectedText(flags, ResultCallbacks.of(value)); } catch (RemoteException e) { value.onError(ThrowableHolder.of(e)); } @@ -118,8 +115,8 @@ public final class IInputContextInvoker { } /** - * Implements - * {@link android.view.inputmethod.InputConnection#getSurroundingText(int, int, int)}. + * Invokes + * {@link IInputContext#getSurroundingText(int, int, int, ISurroundingTextResultCallback)}. * * @param beforeLength {@code beforeLength} parameter to be passed. * @param afterLength {@code afterLength} parameter to be passed. @@ -132,10 +129,9 @@ public final class IInputContextInvoker { public Completable.SurroundingText getSurroundingText(int beforeLength, int afterLength, int flags) { final Completable.SurroundingText value = Completable.createSurroundingText(); - final InputConnectionCommand command = - Commands.getSurroundingText(beforeLength, afterLength, flags, value); try { - mIInputContext.doEdit(command); + mIInputContext.getSurroundingText(beforeLength, afterLength, flags, + ResultCallbacks.of(value)); } catch (RemoteException e) { value.onError(ThrowableHolder.of(e)); } @@ -143,7 +139,7 @@ public final class IInputContextInvoker { } /** - * Implements {@link android.view.inputmethod.InputConnection#getCursorCapsMode(int)}. + * Invokes {@link IInputContext#getCursorCapsMode(int, IIntResultCallback)}. * * @param reqModes {@code reqModes} parameter to be passed. * @return {@link Completable.Int} that can be used to retrieve the invocation result. @@ -153,9 +149,8 @@ public final class IInputContextInvoker { @NonNull public Completable.Int getCursorCapsMode(int reqModes) { final Completable.Int value = Completable.createInt(); - final InputConnectionCommand command = Commands.getCursorCapsMode(reqModes, value); try { - mIInputContext.doEdit(command); + mIInputContext.getCursorCapsMode(reqModes, ResultCallbacks.of(value)); } catch (RemoteException e) { value.onError(ThrowableHolder.of(e)); } @@ -163,8 +158,8 @@ public final class IInputContextInvoker { } /** - * Implements - * {@link android.view.inputmethod.InputConnection#getExtractedText(ExtractedTextRequest, int)}. + * Invokes {@link IInputContext#getExtractedText(ExtractedTextRequest, int, + * IExtractedTextResultCallback)}. * * @param request {@code request} parameter to be passed. * @param flags {@code flags} parameter to be passed. @@ -175,9 +170,8 @@ public final class IInputContextInvoker { @NonNull public Completable.ExtractedText getExtractedText(ExtractedTextRequest request, int flags) { final Completable.ExtractedText value = Completable.createExtractedText(); - final InputConnectionCommand command = Commands.getExtractedText(request, flags, value); try { - mIInputContext.doEdit(command); + mIInputContext.getExtractedText(request, flags, ResultCallbacks.of(value)); } catch (RemoteException e) { value.onError(ThrowableHolder.of(e)); } @@ -185,7 +179,7 @@ public final class IInputContextInvoker { } /** - * Implements {@link android.view.inputmethod.InputConnection#commitText(CharSequence, int)}. + * Invokes {@link IInputContext#commitText(CharSequence, int)}. * * @param text {@code text} parameter to be passed. * @param newCursorPosition {@code newCursorPosition} parameter to be passed. @@ -194,9 +188,8 @@ public final class IInputContextInvoker { */ @AnyThread public boolean commitText(CharSequence text, int newCursorPosition) { - final InputConnectionCommand command = Commands.commitText(text, newCursorPosition); try { - mIInputContext.doEdit(command); + mIInputContext.commitText(text, newCursorPosition); return true; } catch (RemoteException e) { return false; @@ -204,7 +197,7 @@ public final class IInputContextInvoker { } /** - * Implements {@link android.view.inputmethod.InputConnection#commitCompletion(CompletionInfo)}. + * Invokes {@link IInputContext#commitCompletion(CompletionInfo)}. * * @param text {@code text} parameter to be passed. * @return {@code true} if the invocation is completed without {@link RemoteException}. @@ -212,9 +205,8 @@ public final class IInputContextInvoker { */ @AnyThread public boolean commitCompletion(CompletionInfo text) { - final InputConnectionCommand command = Commands.commitCompletion(text); try { - mIInputContext.doEdit(command); + mIInputContext.commitCompletion(text); return true; } catch (RemoteException e) { return false; @@ -222,7 +214,7 @@ public final class IInputContextInvoker { } /** - * Implements {@link android.view.inputmethod.InputConnection#commitCorrection(CorrectionInfo)}. + * Invokes {@link IInputContext#commitCorrection(CorrectionInfo)}. * * @param correctionInfo {@code correctionInfo} parameter to be passed. * @return {@code true} if the invocation is completed without {@link RemoteException}. @@ -230,9 +222,8 @@ public final class IInputContextInvoker { */ @AnyThread public boolean commitCorrection(CorrectionInfo correctionInfo) { - final InputConnectionCommand command = Commands.commitCorrection(correctionInfo); try { - mIInputContext.doEdit(command); + mIInputContext.commitCorrection(correctionInfo); return true; } catch (RemoteException e) { return false; @@ -240,7 +231,7 @@ public final class IInputContextInvoker { } /** - * Implements {@link android.view.inputmethod.InputConnection#setSelection(int, int)}. + * Invokes {@link IInputContext#setSelection(int, int)}. * * @param start {@code start} parameter to be passed. * @param end {@code start} parameter to be passed. @@ -249,9 +240,8 @@ public final class IInputContextInvoker { */ @AnyThread public boolean setSelection(int start, int end) { - final InputConnectionCommand command = Commands.setSelection(start, end); try { - mIInputContext.doEdit(command); + mIInputContext.setSelection(start, end); return true; } catch (RemoteException e) { return false; @@ -259,7 +249,7 @@ public final class IInputContextInvoker { } /** - * Implements {@link android.view.inputmethod.InputConnection#performEditorAction(int)}. + * Invokes {@link IInputContext#performEditorAction(int)}. * * @param actionCode {@code start} parameter to be passed. * @return {@code true} if the invocation is completed without {@link RemoteException}. @@ -267,9 +257,8 @@ public final class IInputContextInvoker { */ @AnyThread public boolean performEditorAction(int actionCode) { - final InputConnectionCommand command = Commands.performEditorAction(actionCode); try { - mIInputContext.doEdit(command); + mIInputContext.performEditorAction(actionCode); return true; } catch (RemoteException e) { return false; @@ -277,7 +266,7 @@ public final class IInputContextInvoker { } /** - * Implements {@link android.view.inputmethod.InputConnection#performContextMenuAction(int)}. + * Invokes {@link IInputContext#performContextMenuAction(id)}. * * @param id {@code id} parameter to be passed. * @return {@code true} if the invocation is completed without {@link RemoteException}. @@ -285,9 +274,8 @@ public final class IInputContextInvoker { */ @AnyThread public boolean performContextMenuAction(int id) { - final InputConnectionCommand command = Commands.performContextMenuAction(id); try { - mIInputContext.doEdit(command); + mIInputContext.performContextMenuAction(id); return true; } catch (RemoteException e) { return false; @@ -295,7 +283,7 @@ public final class IInputContextInvoker { } /** - * Implements {@link android.view.inputmethod.InputConnection#setComposingRegion(int, int)}. + * Invokes {@link IInputContext#setComposingRegion(int, int)}. * * @param start {@code id} parameter to be passed. * @param end {@code id} parameter to be passed. @@ -304,9 +292,8 @@ public final class IInputContextInvoker { */ @AnyThread public boolean setComposingRegion(int start, int end) { - final InputConnectionCommand command = Commands.setComposingRegion(start, end); try { - mIInputContext.doEdit(command); + mIInputContext.setComposingRegion(start, end); return true; } catch (RemoteException e) { return false; @@ -314,8 +301,7 @@ public final class IInputContextInvoker { } /** - * Implements - * {@link android.view.inputmethod.InputConnection#setComposingText(CharSequence, int)}. + * Invokes {@link IInputContext#setComposingText(CharSequence, int)}. * * @param text {@code text} parameter to be passed. * @param newCursorPosition {@code newCursorPosition} parameter to be passed. @@ -324,9 +310,8 @@ public final class IInputContextInvoker { */ @AnyThread public boolean setComposingText(CharSequence text, int newCursorPosition) { - final InputConnectionCommand command = Commands.setComposingText(text, newCursorPosition); try { - mIInputContext.doEdit(command); + mIInputContext.setComposingText(text, newCursorPosition); return true; } catch (RemoteException e) { return false; @@ -334,16 +319,15 @@ public final class IInputContextInvoker { } /** - * Implements {@link android.view.inputmethod.InputConnection#finishComposingText()}. + * Invokes {@link IInputContext#finishComposingText()}. * * @return {@code true} if the invocation is completed without {@link RemoteException}. * {@code false} otherwise. */ @AnyThread public boolean finishComposingText() { - final InputConnectionCommand command = Commands.finishComposingText(); try { - mIInputContext.doEdit(command); + mIInputContext.finishComposingText(); return true; } catch (RemoteException e) { return false; @@ -351,16 +335,15 @@ public final class IInputContextInvoker { } /** - * Implements {@link android.view.inputmethod.InputConnection#beginBatchEdit()}. + * Invokes {@link IInputContext#beginBatchEdit()}. * * @return {@code true} if the invocation is completed without {@link RemoteException}. * {@code false} otherwise. */ @AnyThread public boolean beginBatchEdit() { - final InputConnectionCommand command = Commands.beginBatchEdit(); try { - mIInputContext.doEdit(command); + mIInputContext.beginBatchEdit(); return true; } catch (RemoteException e) { return false; @@ -368,16 +351,15 @@ public final class IInputContextInvoker { } /** - * Implements {@link android.view.inputmethod.InputConnection#endBatchEdit()}. + * Invokes {@link IInputContext#endBatchEdit()}. * * @return {@code true} if the invocation is completed without {@link RemoteException}. * {@code false} otherwise. */ @AnyThread public boolean endBatchEdit() { - final InputConnectionCommand command = Commands.endBatchEdit(); try { - mIInputContext.doEdit(command); + mIInputContext.endBatchEdit(); return true; } catch (RemoteException e) { return false; @@ -385,7 +367,7 @@ public final class IInputContextInvoker { } /** - * Implements {@link android.view.inputmethod.InputConnection#sendKeyEvent(KeyEvent)}. + * Invokes {@link IInputContext#sendKeyEvent(KeyEvent)}. * * @param event {@code event} parameter to be passed. * @return {@code true} if the invocation is completed without {@link RemoteException}. @@ -393,9 +375,8 @@ public final class IInputContextInvoker { */ @AnyThread public boolean sendKeyEvent(KeyEvent event) { - final InputConnectionCommand command = Commands.sendKeyEvent(event); try { - mIInputContext.doEdit(command); + mIInputContext.sendKeyEvent(event); return true; } catch (RemoteException e) { return false; @@ -403,7 +384,7 @@ public final class IInputContextInvoker { } /** - * Implements {@link android.view.inputmethod.InputConnection#clearMetaKeyStates(int)}. + * Invokes {@link IInputContext#clearMetaKeyStates(int)}. * * @param states {@code states} parameter to be passed. * @return {@code true} if the invocation is completed without {@link RemoteException}. @@ -411,9 +392,8 @@ public final class IInputContextInvoker { */ @AnyThread public boolean clearMetaKeyStates(int states) { - final InputConnectionCommand command = Commands.clearMetaKeyStates(states); try { - mIInputContext.doEdit(command); + mIInputContext.clearMetaKeyStates(states); return true; } catch (RemoteException e) { return false; @@ -421,7 +401,7 @@ public final class IInputContextInvoker { } /** - * Implements {@link android.view.inputmethod.InputConnection#deleteSurroundingText(int, int)}. + * Invokes {@link IInputContext#deleteSurroundingText(int, int)}. * * @param beforeLength {@code beforeLength} parameter to be passed. * @param afterLength {@code afterLength} parameter to be passed. @@ -430,10 +410,8 @@ public final class IInputContextInvoker { */ @AnyThread public boolean deleteSurroundingText(int beforeLength, int afterLength) { - final InputConnectionCommand command = - Commands.deleteSurroundingText(beforeLength, afterLength); try { - mIInputContext.doEdit(command); + mIInputContext.deleteSurroundingText(beforeLength, afterLength); return true; } catch (RemoteException e) { return false; @@ -441,8 +419,7 @@ public final class IInputContextInvoker { } /** - * Implements - * {@link android.view.inputmethod.InputConnection#deleteSurroundingTextInCodePoints(int, int)}. + * Invokes {@link IInputContext#deleteSurroundingTextInCodePoints(int, int)}. * * @param beforeLength {@code beforeLength} parameter to be passed. * @param afterLength {@code afterLength} parameter to be passed. @@ -451,10 +428,8 @@ public final class IInputContextInvoker { */ @AnyThread public boolean deleteSurroundingTextInCodePoints(int beforeLength, int afterLength) { - final InputConnectionCommand command = - Commands.deleteSurroundingTextInCodePoints(beforeLength, afterLength); try { - mIInputContext.doEdit(command); + mIInputContext.deleteSurroundingTextInCodePoints(beforeLength, afterLength); return true; } catch (RemoteException e) { return false; @@ -462,16 +437,15 @@ public final class IInputContextInvoker { } /** - * Implements {@link android.view.inputmethod.InputConnection#performSpellCheck()}. + * Invokes {@link IInputContext#performSpellCheck()}. * * @return {@code true} if the invocation is completed without {@link RemoteException}. * {@code false} otherwise. */ @AnyThread public boolean performSpellCheck() { - final InputConnectionCommand command = Commands.performSpellCheck(); try { - mIInputContext.doEdit(command); + mIInputContext.performSpellCheck(); return true; } catch (RemoteException e) { return false; @@ -479,8 +453,7 @@ public final class IInputContextInvoker { } /** - * Implements - * {@link android.view.inputmethod.InputConnection#performPrivateCommand(String, Bundle)}. + * Invokes {@link IInputContext#performPrivateCommand(String, Bundle)}. * * @param action {@code action} parameter to be passed. * @param data {@code data} parameter to be passed. @@ -489,9 +462,8 @@ public final class IInputContextInvoker { */ @AnyThread public boolean performPrivateCommand(String action, Bundle data) { - final InputConnectionCommand command = Commands.performPrivateCommand(action, data); try { - mIInputContext.doEdit(command); + mIInputContext.performPrivateCommand(action, data); return true; } catch (RemoteException e) { return false; @@ -499,7 +471,7 @@ public final class IInputContextInvoker { } /** - * Implements {@link android.view.inputmethod.InputConnection#requestCursorUpdates(int)}. + * Invokes {@link IInputContext#requestCursorUpdates(int, IIntResultCallback)}. * * @param cursorUpdateMode {@code cursorUpdateMode} parameter to be passed. * @return {@link Completable.Boolean} that can be used to retrieve the invocation result. @@ -509,10 +481,8 @@ public final class IInputContextInvoker { @NonNull public Completable.Boolean requestCursorUpdates(int cursorUpdateMode) { final Completable.Boolean value = Completable.createBoolean(); - final InputConnectionCommand command = - Commands.requestCursorUpdates(cursorUpdateMode, value); try { - mIInputContext.doEdit(command); + mIInputContext.requestCursorUpdates(cursorUpdateMode, ResultCallbacks.of(value)); } catch (RemoteException e) { value.onError(ThrowableHolder.of(e)); } @@ -520,8 +490,8 @@ public final class IInputContextInvoker { } /** - * Implements {@link android.view.inputmethod.InputConnection#commitContent(InputContentInfo, - * int, Bundle)}. + * Invokes + * {@link IInputContext#commitContent(InputContentInfo, int, Bundle, IIntResultCallback)}. * * @param inputContentInfo {@code inputContentInfo} parameter to be passed. * @param flags {@code flags} parameter to be passed. @@ -534,10 +504,8 @@ public final class IInputContextInvoker { public Completable.Boolean commitContent(InputContentInfo inputContentInfo, int flags, Bundle opts) { final Completable.Boolean value = Completable.createBoolean(); - final InputConnectionCommand command = - Commands.commitContent(inputContentInfo, flags, opts, value); try { - mIInputContext.doEdit(command); + mIInputContext.commitContent(inputContentInfo, flags, opts, ResultCallbacks.of(value)); } catch (RemoteException e) { value.onError(ThrowableHolder.of(e)); } @@ -545,7 +513,7 @@ public final class IInputContextInvoker { } /** - * Implements {@link android.view.inputmethod.InputConnection#setImeConsumesInput(boolean)}. + * Invokes {@link IInputContext#setImeConsumesInput(boolean)}. * * @param imeConsumesInput {@code imeConsumesInput} parameter to be passed. * @return {@code true} if the invocation is completed without {@link RemoteException}. @@ -553,341 +521,11 @@ public final class IInputContextInvoker { */ @AnyThread public boolean setImeConsumesInput(boolean imeConsumesInput) { - final InputConnectionCommand command = Commands.setImeConsumesInput(imeConsumesInput); try { - mIInputContext.doEdit(command); + mIInputContext.setImeConsumesInput(imeConsumesInput); return true; } catch (RemoteException e) { return false; } } - - /** - * Defines the data packing rules from {@link android.view.inputmethod.InputConnection} API - * params into {@link InputConnectionCommand} fields. - * - * Rules need to be in sync with {@link com.android.internal.view.IInputConnectionWrapper} and - * {@link InputMethodDebug#dumpInputConnectionCommand(InputConnectionCommand)}. - */ - private static final class Commands { - /** - * Not intended to be instantiated. - */ - private Commands() { } - - @AnyThread - @NonNull - static InputConnectionCommand getTextAfterCursor(int n, int flags, - @NonNull Completable.CharSequence returnValue) { - return InputConnectionCommand.create( - InputConnectionCommandType.GET_TEXT_AFTER_CURSOR, - n, - 0, - flags, - null, - null, - null, - InputConnectionCommand.ParcelableType.NULL, - null, - returnValue); - } - - @AnyThread - @NonNull - static InputConnectionCommand getTextBeforeCursor(int n, int flags, - @NonNull Completable.CharSequence returnValue) { - return InputConnectionCommand.create( - InputConnectionCommandType.GET_TEXT_BEFORE_CURSOR, - n, - 0, - flags, - null, - null, - null, - InputConnectionCommand.ParcelableType.NULL, - null, - returnValue); - } - - @AnyThread - @NonNull - static InputConnectionCommand getSelectedText(int flags, - @NonNull Completable.CharSequence returnValue) { - return InputConnectionCommand.create( - InputConnectionCommandType.GET_SELECTED_TEXT, - 0, - 0, - flags, - null, - null, - null, - InputConnectionCommand.ParcelableType.NULL, - null, - returnValue); - } - - @AnyThread - @NonNull - static InputConnectionCommand getSurroundingText(int beforeLength, int afterLength, - int flags, @NonNull Completable.SurroundingText returnValue) { - return InputConnectionCommand.create( - InputConnectionCommandType.GET_SURROUNDING_TEXT, - beforeLength, - afterLength, - flags, - null, - null, - null, - InputConnectionCommand.ParcelableType.NULL, - null, - returnValue); - } - - @AnyThread - @NonNull - static InputConnectionCommand getCursorCapsMode(int reqModes, - @NonNull Completable.Int returnValue) { - return InputConnectionCommand.create( - InputConnectionCommandType.GET_CURSOR_CAPS_MODE, - reqModes, - 0, - 0, - null, - null, - null, - InputConnectionCommand.ParcelableType.NULL, - null, - returnValue); - } - - @AnyThread - @NonNull - static InputConnectionCommand getExtractedText(@Nullable ExtractedTextRequest request, - int flags, @NonNull Completable.ExtractedText returnValue) { - return InputConnectionCommand.create( - InputConnectionCommandType.GET_EXTRACTED_TEXT, - 0, - 0, - flags, - null, - null, - null, - InputConnectionCommand.ParcelableType.EXTRACTED_TEXT_REQUEST, - request, - returnValue); - } - - @AnyThread - @NonNull - static InputConnectionCommand commitText(@Nullable CharSequence text, - int newCursorPosition) { - return InputConnectionCommand.create( - InputConnectionCommandType.COMMIT_TEXT, - newCursorPosition, - 0, - 0, - text); - } - - @AnyThread - @NonNull - static InputConnectionCommand commitCompletion(@Nullable CompletionInfo text) { - return InputConnectionCommand.create( - InputConnectionCommandType.COMMIT_COMPLETION, - 0, - 0, - 0, - null, - null, - null, - InputConnectionCommand.ParcelableType.COMPLETION_INFO, - text); - } - - @AnyThread - @NonNull - static InputConnectionCommand commitCorrection(@Nullable CorrectionInfo correctionInfo) { - return InputConnectionCommand.create( - InputConnectionCommandType.COMMIT_CORRECTION, - 0, - 0, - 0, - null, - null, - null, - InputConnectionCommand.ParcelableType.CORRECTION_INFO, - correctionInfo); - } - - @AnyThread - @NonNull - static InputConnectionCommand setSelection(int start, int end) { - return InputConnectionCommand.create( - InputConnectionCommandType.SET_SELECTION, - start, - end); - } - - @AnyThread - @NonNull - static InputConnectionCommand performEditorAction(int actionCode) { - return InputConnectionCommand.create( - InputConnectionCommandType.PERFORM_EDITOR_ACTION, - actionCode); - } - - @AnyThread - @NonNull - static InputConnectionCommand performContextMenuAction(int id) { - return InputConnectionCommand.create( - InputConnectionCommandType.PERFORM_CONTEXT_MENU_ACTION, - id); - } - - @AnyThread - @NonNull - static InputConnectionCommand setComposingRegion(int start, int end) { - return InputConnectionCommand.create( - InputConnectionCommandType.SET_COMPOSING_REGION, - start, - end); - } - - @AnyThread - @NonNull - static InputConnectionCommand setComposingText(@Nullable CharSequence text, - int newCursorPosition) { - return InputConnectionCommand.create( - InputConnectionCommandType.SET_COMPOSING_TEXT, - newCursorPosition, - 0, - 0, - text); - } - - @AnyThread - @NonNull - static InputConnectionCommand finishComposingText() { - return InputConnectionCommand.create( - InputConnectionCommandType.FINISH_COMPOSING_TEXT); - } - - @AnyThread - @NonNull - static InputConnectionCommand beginBatchEdit() { - return InputConnectionCommand.create( - InputConnectionCommandType.BEGIN_BATCH_EDIT); - } - - @AnyThread - @NonNull - static InputConnectionCommand endBatchEdit() { - return InputConnectionCommand.create( - InputConnectionCommandType.END_BATCH_EDIT); - } - - @AnyThread - @NonNull - static InputConnectionCommand sendKeyEvent(@Nullable KeyEvent event) { - return InputConnectionCommand.create( - InputConnectionCommandType.SEND_KEY_EVENT, - 0, - 0, - 0, - null, - null, - null, - InputConnectionCommand.ParcelableType.KEY_EVENT, - event); - } - - @AnyThread - @NonNull - static InputConnectionCommand clearMetaKeyStates(int states) { - return InputConnectionCommand.create( - InputConnectionCommandType.CLEAR_META_KEY_STATES, - states); - } - - @AnyThread - @NonNull - static InputConnectionCommand deleteSurroundingText(int beforeLength, int afterLength) { - return InputConnectionCommand.create( - InputConnectionCommandType.DELETE_SURROUNDING_TEXT, - beforeLength, - afterLength); - } - - @AnyThread - @NonNull - static InputConnectionCommand deleteSurroundingTextInCodePoints(int beforeLength, - int afterLength) { - return InputConnectionCommand.create( - InputConnectionCommandType.DELETE_SURROUNDING_TEXT_IN_CODE_POINTS, - beforeLength, - afterLength); - } - - @AnyThread - @NonNull - static InputConnectionCommand performSpellCheck() { - return InputConnectionCommand.create(InputConnectionCommandType.PERFORM_SPELL_CHECK); - } - - @AnyThread - @NonNull - static InputConnectionCommand performPrivateCommand(@Nullable String action, - @Nullable Bundle data) { - return InputConnectionCommand.create( - InputConnectionCommandType.PERFORM_PRIVATE_COMMAND, - 0, - 0, - 0, - null, - action, - data); - } - - @AnyThread - @NonNull - static InputConnectionCommand requestCursorUpdates(int cursorUpdateMode, - @NonNull Completable.Boolean returnValue) { - return InputConnectionCommand.create( - InputConnectionCommandType.REQUEST_CURSOR_UPDATES, - cursorUpdateMode, - 0, - 0, - null, - null, - null, - InputConnectionCommand.ParcelableType.NULL, - null, - returnValue); - } - - @AnyThread - @NonNull - static InputConnectionCommand commitContent(@Nullable InputContentInfo inputContentInfo, - int flags, @Nullable Bundle opts, @NonNull Completable.Boolean returnValue) { - return InputConnectionCommand.create( - InputConnectionCommandType.COMMIT_CONTENT, - 0, - 0, - flags, - null, - null, - opts, - InputConnectionCommand.ParcelableType.INPUT_CONTENT_INFO, - inputContentInfo, - returnValue); - } - - @AnyThread - @NonNull - static InputConnectionCommand setImeConsumesInput(boolean imeConsumesInput) { - return InputConnectionCommand.create( - InputConnectionCommandType.SET_IME_CONSUMES_INPUT, - imeConsumesInput ? 1 : 0); - } - } } diff --git a/core/java/com/android/internal/inputmethod/InputConnectionCommand.aidl b/core/java/com/android/internal/inputmethod/InputConnectionCommand.aidl deleted file mode 100644 index c7c2ad87a58cb..0000000000000 --- a/core/java/com/android/internal/inputmethod/InputConnectionCommand.aidl +++ /dev/null @@ -1,19 +0,0 @@ -/* - * Copyright (C) 2021 The Android Open Source Project - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package com.android.internal.inputmethod; - -parcelable InputConnectionCommand; diff --git a/core/java/com/android/internal/inputmethod/InputConnectionCommand.java b/core/java/com/android/internal/inputmethod/InputConnectionCommand.java deleted file mode 100644 index 4116b028fbbf9..0000000000000 --- a/core/java/com/android/internal/inputmethod/InputConnectionCommand.java +++ /dev/null @@ -1,460 +0,0 @@ -/* - * Copyright (C) 2021 The Android Open Source Project - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package com.android.internal.inputmethod; - -import static java.lang.annotation.RetentionPolicy.SOURCE; - -import android.annotation.AnyThread; -import android.annotation.IntDef; -import android.annotation.IntRange; -import android.annotation.NonNull; -import android.annotation.Nullable; -import android.os.Bundle; -import android.os.IBinder; -import android.os.Parcel; -import android.os.Parcelable; -import android.text.TextUtils; -import android.util.Log; -import android.view.KeyEvent; -import android.view.inputmethod.CompletionInfo; -import android.view.inputmethod.CorrectionInfo; -import android.view.inputmethod.ExtractedTextRequest; -import android.view.inputmethod.InputContentInfo; - -import java.lang.annotation.Retention; - -/** - * Defines the command message to be used for IMEs to remotely invoke - * {@link android.view.inputmethod.InputConnection} APIs in the IME client process then receive - * results. - */ -public final class InputConnectionCommand implements Parcelable { - private static final String TAG = "InputConnectionCommand"; - - @Retention(SOURCE) - @IntDef(value = { - ResultCallbackType.NULL, - ResultCallbackType.BOOLEAN, - ResultCallbackType.INT, - ResultCallbackType.CHAR_SEQUENCE, - ResultCallbackType.EXTRACTED_TEXT, - ResultCallbackType.SURROUNDING_TEXT, - }) - @interface ResultCallbackType { - int NULL = 0; - int BOOLEAN = 1; - int INT = 2; - int CHAR_SEQUENCE = 3; - int EXTRACTED_TEXT = 4; - int SURROUNDING_TEXT = 5; - } - - @Retention(SOURCE) - @IntDef(value = { - ParcelableType.NULL, - ParcelableType.EXTRACTED_TEXT_REQUEST, - ParcelableType.COMPLETION_INFO, - ParcelableType.CORRECTION_INFO, - ParcelableType.KEY_EVENT, - ParcelableType.INPUT_CONTENT_INFO, - }) - @interface ParcelableType { - int NULL = 0; - int EXTRACTED_TEXT_REQUEST = 1; - int COMPLETION_INFO = 2; - int CORRECTION_INFO = 3; - int KEY_EVENT = 4; - int INPUT_CONTENT_INFO = 5; - } - - @Retention(SOURCE) - @IntDef(flag = true, value = { - FieldMask.INT_ARG0, - FieldMask.INT_ARG1, - FieldMask.FLAGS, - FieldMask.CHAR_SEQUENCE, - FieldMask.STRING, - FieldMask.BUNDLE, - FieldMask.PARCELABLE, - FieldMask.CALLBACK, - }) - @interface FieldMask { - int INT_ARG0 = 1 << 0; - int INT_ARG1 = 1 << 1; - int FLAGS = 1 << 2; - int CHAR_SEQUENCE = 1 << 3; - int STRING = 1 << 4; - int BUNDLE = 1 << 5; - int PARCELABLE = 1 << 6; - int CALLBACK = 1 << 7; - } - - @IntRange(from = InputConnectionCommandType.FIRST_COMMAND, - to = InputConnectionCommandType.LAST_COMMAND) - @InputConnectionCommandType - public final int mCommandType; - public final int mIntArg0; - public final int mIntArg1; - public final int mFlags; - public final CharSequence mCharSequence; - public final String mString; - public final Bundle mBundle; - @ParcelableType - public final int mParcelableType; - public final Parcelable mParcelable; - @ResultCallbackType - public final int mResultCallbackType; - public final IBinder mResultCallback; - - private InputConnectionCommand( - @IntRange( - from = InputConnectionCommandType.FIRST_COMMAND, - to = InputConnectionCommandType.LAST_COMMAND) - @InputConnectionCommandType int type, int intArg0, int intArg1, int flags, - @Nullable CharSequence charSequence, @Nullable String string, @Nullable Bundle bundle, - @ParcelableType int parcelableType, @Nullable Parcelable parcelable, - @ResultCallbackType int resultCallbackType, @Nullable IBinder resultCallback) { - if (type < InputConnectionCommandType.FIRST_COMMAND - || InputConnectionCommandType.LAST_COMMAND < type) { - throw new IllegalArgumentException("Unknown type=" + type); - } - mCommandType = type; - mIntArg0 = intArg0; - mIntArg1 = intArg1; - mFlags = flags; - mCharSequence = charSequence; - mString = string; - mBundle = bundle; - mParcelableType = parcelableType; - mParcelable = parcelable; - mResultCallbackType = resultCallbackType; - mResultCallback = resultCallback; - } - - /** - * Creates {@link InputConnectionCommand} with the given {@link InputConnectionCommandType}. - * - * @param type {@link InputConnectionCommandType} to be set. - * @return An {@link InputConnectionCommand} that is initialized with {@code type}. - */ - @NonNull - public static InputConnectionCommand create( - @IntRange( - from = InputConnectionCommandType.FIRST_COMMAND, - to = InputConnectionCommandType.LAST_COMMAND) - @InputConnectionCommandType int type) { - return create(type, 0); - } - - @NonNull - static InputConnectionCommand create( - @IntRange( - from = InputConnectionCommandType.FIRST_COMMAND, - to = InputConnectionCommandType.LAST_COMMAND) - @InputConnectionCommandType int type, int intArg0) { - return create(type, intArg0, 0); - } - - @NonNull - static InputConnectionCommand create( - @IntRange( - from = InputConnectionCommandType.FIRST_COMMAND, - to = InputConnectionCommandType.LAST_COMMAND) - @InputConnectionCommandType int type, int intArg0, int intArg1) { - return create(type, intArg0, intArg1, 0, null); - } - - @NonNull - static InputConnectionCommand create( - @IntRange( - from = InputConnectionCommandType.FIRST_COMMAND, - to = InputConnectionCommandType.LAST_COMMAND) - @InputConnectionCommandType int type, int intArg0, - int intArg1, int flags, @Nullable CharSequence charSequence) { - return create(type, intArg0, intArg1, flags, charSequence, null, null); - } - - @NonNull - static InputConnectionCommand create( - @IntRange( - from = InputConnectionCommandType.FIRST_COMMAND, - to = InputConnectionCommandType.LAST_COMMAND) - @InputConnectionCommandType int type, - int intArg0, int intArg1, int flags, @Nullable CharSequence charSequence, - @Nullable String string, @Nullable Bundle bundle) { - return create(type, intArg0, intArg1, flags, charSequence, string, - bundle, ParcelableType.NULL, null); - } - - @NonNull - static InputConnectionCommand create( - @IntRange( - from = InputConnectionCommandType.FIRST_COMMAND, - to = InputConnectionCommandType.LAST_COMMAND) - @InputConnectionCommandType int type, - int intArg0, int intArg1, int flags, @Nullable CharSequence charSequence, - @Nullable String string, @Nullable Bundle bundle, - @ParcelableType int parcelableType, @Nullable Parcelable parcelable) { - return new InputConnectionCommand(type, intArg0, intArg1, flags, charSequence, string, - bundle, parcelableType, parcelable, ResultCallbackType.NULL, null); - } - - @NonNull - static InputConnectionCommand create( - @IntRange( - from = InputConnectionCommandType.FIRST_COMMAND, - to = InputConnectionCommandType.LAST_COMMAND) - @InputConnectionCommandType int type, - int intArg0, int intArg1, int flags, @Nullable CharSequence charSequence, - @Nullable String string, @Nullable Bundle bundle, - @ParcelableType int parcelableType, @Nullable Parcelable parcelable, - @NonNull Completable.Boolean returnValue) { - return new InputConnectionCommand(type, intArg0, intArg1, flags, charSequence, string, - bundle, parcelableType, parcelable, - ResultCallbackType.BOOLEAN, ResultCallbacks.of(returnValue)); - } - - @NonNull - static InputConnectionCommand create( - @IntRange( - from = InputConnectionCommandType.FIRST_COMMAND, - to = InputConnectionCommandType.LAST_COMMAND) - @InputConnectionCommandType int type, - int intArg0, int intArg1, int flags, @Nullable CharSequence charSequence, - @Nullable String string, @Nullable Bundle bundle, - @ParcelableType int parcelableType, @Nullable Parcelable parcelable, - @NonNull Completable.Int returnValue) { - return new InputConnectionCommand(type, intArg0, intArg1, flags, charSequence, string, - bundle, parcelableType, parcelable, - ResultCallbackType.INT, ResultCallbacks.of(returnValue)); - } - - @NonNull - static InputConnectionCommand create( - @IntRange( - from = InputConnectionCommandType.FIRST_COMMAND, - to = InputConnectionCommandType.LAST_COMMAND) - @InputConnectionCommandType int type, - int intArg0, int intArg1, int flags, @Nullable CharSequence charSequence, - @Nullable String string, @Nullable Bundle bundle, - @ParcelableType int parcelableType, @Nullable Parcelable parcelable, - @NonNull Completable.CharSequence returnValue) { - return new InputConnectionCommand(type, intArg0, intArg1, flags, charSequence, string, - bundle, parcelableType, parcelable, - ResultCallbackType.CHAR_SEQUENCE, ResultCallbacks.of(returnValue)); - } - - @NonNull - static InputConnectionCommand create( - @IntRange( - from = InputConnectionCommandType.FIRST_COMMAND, - to = InputConnectionCommandType.LAST_COMMAND) - @InputConnectionCommandType int type, - int intArg0, int intArg1, int flags, @Nullable CharSequence charSequence, - @Nullable String string, @Nullable Bundle bundle, - @ParcelableType int parcelableType, @Nullable Parcelable parcelable, - @NonNull Completable.ExtractedText returnValue) { - return new InputConnectionCommand(type, intArg0, intArg1, flags, charSequence, string, - bundle, parcelableType, parcelable, - ResultCallbackType.EXTRACTED_TEXT, ResultCallbacks.of(returnValue)); - } - - @NonNull - static InputConnectionCommand create( - @IntRange( - from = InputConnectionCommandType.FIRST_COMMAND, - to = InputConnectionCommandType.LAST_COMMAND) - @InputConnectionCommandType int type, - int intArg0, int intArg1, int flags, @Nullable CharSequence charSequence, - @Nullable String string, @Nullable Bundle bundle, - @ParcelableType int parcelableType, @Nullable Parcelable parcelable, - @NonNull Completable.SurroundingText returnValue) { - return new InputConnectionCommand(type, intArg0, intArg1, flags, charSequence, string, - bundle, parcelableType, parcelable, - ResultCallbackType.SURROUNDING_TEXT, ResultCallbacks.of(returnValue)); - } - - /** - * {@inheritDoc} - */ - @AnyThread - @Override - public int describeContents() { - int result = 0; - if (mBundle != null) { - result |= mBundle.describeContents(); - } - if (mParcelable != null) { - result |= mParcelable.describeContents(); - } - // Here we assume other objects will never contain FDs to be parcelled. - return result; - } - - /** - * {@inheritDoc} - */ - @AnyThread - @Override - public void writeToParcel(Parcel dest, int flags) { - dest.writeInt(mCommandType); - - @FieldMask final int fieldMask = getFieldMask(); - dest.writeInt(fieldMask); - if ((fieldMask & FieldMask.INT_ARG0) != 0) { - dest.writeInt(mIntArg0); - } - if ((fieldMask & FieldMask.INT_ARG1) != 0) { - dest.writeInt(mIntArg1); - } - if ((fieldMask & FieldMask.FLAGS) != 0) { - dest.writeInt(mFlags); - } - if ((fieldMask & FieldMask.CHAR_SEQUENCE) != 0) { - TextUtils.writeToParcel(mCharSequence, dest, flags); - } - if ((fieldMask & FieldMask.STRING) != 0) { - dest.writeString(mString); - } - if ((fieldMask & FieldMask.BUNDLE) != 0) { - dest.writeBundle(mBundle); - } - if ((fieldMask & FieldMask.PARCELABLE) != 0) { - dest.writeInt(mParcelableType); - dest.writeTypedObject(mParcelable, flags); - } - if ((fieldMask & FieldMask.CALLBACK) != 0) { - dest.writeInt(mResultCallbackType); - dest.writeStrongBinder(mResultCallback); - } - } - - @FieldMask - @AnyThread - private int getFieldMask() { - return (mIntArg0 != 0 ? FieldMask.INT_ARG0 : 0) - | (mIntArg1 != 0 ? FieldMask.INT_ARG1 : 0) - | (mFlags != 0 ? FieldMask.FLAGS : 0) - | (mCharSequence != null ? FieldMask.CHAR_SEQUENCE : 0) - | (mString != null ? FieldMask.STRING : 0) - | (mBundle != null ? FieldMask.BUNDLE : 0) - | (mParcelableType != ParcelableType.NULL ? FieldMask.PARCELABLE : 0) - | (mResultCallbackType != ResultCallbackType.NULL ? FieldMask.CALLBACK : 0); - } - - @AnyThread - @Nullable - private static InputConnectionCommand createFromParcel(@NonNull Parcel source) { - final int type = source.readInt(); - if (type < InputConnectionCommandType.FIRST_COMMAND - || InputConnectionCommandType.LAST_COMMAND < type) { - Log.e(TAG, "Invalid InputConnectionCommand type=" + type); - return null; - } - - @FieldMask final int fieldMask = source.readInt(); - final int intArg0 = (fieldMask & FieldMask.INT_ARG0) != 0 ? source.readInt() : 0; - final int intArg1 = (fieldMask & FieldMask.INT_ARG1) != 0 ? source.readInt() : 0; - final int flags = (fieldMask & FieldMask.FLAGS) != 0 ? source.readInt() : 0; - final CharSequence charSequence = (fieldMask & FieldMask.CHAR_SEQUENCE) != 0 - ? TextUtils.CHAR_SEQUENCE_CREATOR.createFromParcel(source) : null; - final String string = (fieldMask & FieldMask.STRING) != 0 ? source.readString() : null; - final Bundle bundle = (fieldMask & FieldMask.BUNDLE) != 0 ? source.readBundle() : null; - - @ParcelableType final int parcelableType; - final Parcelable parcelable; - if ((fieldMask & FieldMask.PARCELABLE) != 0) { - parcelableType = source.readInt(); - switch (parcelableType) { - case ParcelableType.NULL: - Log.e(TAG, "Unexpected ParcelableType=NULL"); - return null; - case ParcelableType.EXTRACTED_TEXT_REQUEST: - parcelable = source.readTypedObject(ExtractedTextRequest.CREATOR); - break; - case ParcelableType.COMPLETION_INFO: - parcelable = source.readTypedObject(CompletionInfo.CREATOR); - break; - case ParcelableType.CORRECTION_INFO: - parcelable = source.readTypedObject(CorrectionInfo.CREATOR); - break; - case ParcelableType.KEY_EVENT: - parcelable = source.readTypedObject(KeyEvent.CREATOR); - break; - case ParcelableType.INPUT_CONTENT_INFO: - parcelable = source.readTypedObject(InputContentInfo.CREATOR); - break; - default: - Log.e(TAG, "Unknown ParcelableType=" + parcelableType); - return null; - } - } else { - parcelableType = ParcelableType.NULL; - parcelable = null; - } - @ResultCallbackType final int resultCallbackType; - final IBinder resultCallback; - if ((fieldMask & FieldMask.CALLBACK) != 0) { - resultCallbackType = source.readInt(); - switch (resultCallbackType) { - case ResultCallbackType.NULL: - Log.e(TAG, "Unexpected ResultCallbackType=NULL"); - return null; - case ResultCallbackType.BOOLEAN: - case ResultCallbackType.INT: - case ResultCallbackType.CHAR_SEQUENCE: - case ResultCallbackType.EXTRACTED_TEXT: - case ResultCallbackType.SURROUNDING_TEXT: - resultCallback = source.readStrongBinder(); - break; - default: - Log.e(TAG, "Unknown ResultCallbackType=" + resultCallbackType); - return null; - } - } else { - resultCallbackType = ResultCallbackType.NULL; - resultCallback = null; - } - return new InputConnectionCommand(type, intArg0, intArg1, flags, charSequence, string, - bundle, parcelableType, parcelable, resultCallbackType, resultCallback); - } - - /** - * Used to make this class parcelable. - */ - public static final Parcelable.Creator CREATOR = - new Parcelable.Creator() { - @AnyThread - @Nullable - @Override - public InputConnectionCommand createFromParcel(Parcel source) { - try { - return InputConnectionCommand.createFromParcel(source); - } catch (Exception e) { - Log.e(TAG, "Returning null due to exception.", e); - return null; - } - } - - @AnyThread - @NonNull - @Override - public InputConnectionCommand[] newArray(int size) { - return new InputConnectionCommand[size]; - } - }; -} diff --git a/core/java/com/android/internal/inputmethod/InputConnectionCommandType.java b/core/java/com/android/internal/inputmethod/InputConnectionCommandType.java deleted file mode 100644 index 1eb0101115e85..0000000000000 --- a/core/java/com/android/internal/inputmethod/InputConnectionCommandType.java +++ /dev/null @@ -1,84 +0,0 @@ -/* - * Copyright (C) 2021 The Android Open Source Project - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package com.android.internal.inputmethod; - -import static java.lang.annotation.RetentionPolicy.SOURCE; - -import android.annotation.IntDef; - -import java.lang.annotation.Retention; - -@Retention(SOURCE) -@IntDef(value = { - InputConnectionCommandType.BEGIN_BATCH_EDIT, - InputConnectionCommandType.CLEAR_META_KEY_STATES, - InputConnectionCommandType.COMMIT_COMPLETION, - InputConnectionCommandType.COMMIT_CONTENT, - InputConnectionCommandType.COMMIT_CORRECTION, - InputConnectionCommandType.COMMIT_TEXT, - InputConnectionCommandType.DELETE_SURROUNDING_TEXT, - InputConnectionCommandType.DELETE_SURROUNDING_TEXT_IN_CODE_POINTS, - InputConnectionCommandType.END_BATCH_EDIT, - InputConnectionCommandType.FINISH_COMPOSING_TEXT, - InputConnectionCommandType.GET_CURSOR_CAPS_MODE, - InputConnectionCommandType.GET_EXTRACTED_TEXT, - InputConnectionCommandType.GET_SELECTED_TEXT, - InputConnectionCommandType.GET_SURROUNDING_TEXT, - InputConnectionCommandType.GET_TEXT_AFTER_CURSOR, - InputConnectionCommandType.GET_TEXT_BEFORE_CURSOR, - InputConnectionCommandType.PERFORM_CONTEXT_MENU_ACTION, - InputConnectionCommandType.PERFORM_EDITOR_ACTION, - InputConnectionCommandType.PERFORM_SPELL_CHECK, - InputConnectionCommandType.REQUEST_CURSOR_UPDATES, - InputConnectionCommandType.SEND_KEY_EVENT, - InputConnectionCommandType.SET_COMPOSING_REGION, - InputConnectionCommandType.SET_COMPOSING_TEXT, - InputConnectionCommandType.SET_IME_CONSUMES_INPUT, - InputConnectionCommandType.SET_SELECTION, -}) -public @interface InputConnectionCommandType { - int FIRST_COMMAND = 1; - - int BEGIN_BATCH_EDIT = FIRST_COMMAND; - int CLEAR_META_KEY_STATES = 2; - int COMMIT_COMPLETION = 3; - int COMMIT_CONTENT = 4; - int COMMIT_CORRECTION = 5; - int COMMIT_TEXT = 6; - int DELETE_SURROUNDING_TEXT = 7; - int DELETE_SURROUNDING_TEXT_IN_CODE_POINTS = 8; - int END_BATCH_EDIT = 9; - int FINISH_COMPOSING_TEXT = 10; - int GET_CURSOR_CAPS_MODE = 11; - int GET_EXTRACTED_TEXT = 12; - int GET_SELECTED_TEXT = 13; - int GET_SURROUNDING_TEXT = 14; - int GET_TEXT_AFTER_CURSOR = 15; - int GET_TEXT_BEFORE_CURSOR = 16; - int PERFORM_CONTEXT_MENU_ACTION = 17; - int PERFORM_EDITOR_ACTION = 18; - int PERFORM_SPELL_CHECK = 19; - int PERFORM_PRIVATE_COMMAND = 20; - int REQUEST_CURSOR_UPDATES = 21; - int SEND_KEY_EVENT = 22; - int SET_COMPOSING_REGION = 23; - int SET_COMPOSING_TEXT = 24; - int SET_IME_CONSUMES_INPUT = 25; - int SET_SELECTION = 26; - - int LAST_COMMAND = SET_SELECTION; -} diff --git a/core/java/com/android/internal/inputmethod/InputMethodDebug.java b/core/java/com/android/internal/inputmethod/InputMethodDebug.java index 0475ed09bdd2d..a00b993749a52 100644 --- a/core/java/com/android/internal/inputmethod/InputMethodDebug.java +++ b/core/java/com/android/internal/inputmethod/InputMethodDebug.java @@ -18,7 +18,6 @@ package com.android.internal.inputmethod; import android.annotation.AnyThread; import android.annotation.NonNull; -import android.annotation.Nullable; import android.view.WindowManager; import android.view.WindowManager.LayoutParams.SoftInputModeFlags; @@ -242,133 +241,6 @@ public final class InputMethodDebug { } } - /** - * Converts {@link InputConnectionCommandType} to human readable {@link String}. - */ - public static String inputConnectionCommandTypeToString(@InputConnectionCommandType int type) { - switch (type) { - case InputConnectionCommandType.BEGIN_BATCH_EDIT: - return "beginBatchEdit"; - case InputConnectionCommandType.CLEAR_META_KEY_STATES: - return "clearMetaKeyStates"; - case InputConnectionCommandType.COMMIT_COMPLETION: - return "commitCompletion"; - case InputConnectionCommandType.COMMIT_CONTENT: - return "commitContent"; - case InputConnectionCommandType.COMMIT_CORRECTION: - return "commitCorrection"; - case InputConnectionCommandType.COMMIT_TEXT: - return "commitText"; - case InputConnectionCommandType.DELETE_SURROUNDING_TEXT: - return "deleteSurroundingText"; - case InputConnectionCommandType.DELETE_SURROUNDING_TEXT_IN_CODE_POINTS: - return "deleteSurroundingTextInCodePoints"; - case InputConnectionCommandType.END_BATCH_EDIT: - return "endBatchEdit"; - case InputConnectionCommandType.FINISH_COMPOSING_TEXT: - return "finishComposingText"; - case InputConnectionCommandType.GET_CURSOR_CAPS_MODE: - return "getCursorCapsMode"; - case InputConnectionCommandType.GET_EXTRACTED_TEXT: - return "getExtractedText"; - case InputConnectionCommandType.GET_SELECTED_TEXT: - return "getSelectedText"; - case InputConnectionCommandType.GET_SURROUNDING_TEXT: - return "getSurroundingText"; - case InputConnectionCommandType.GET_TEXT_AFTER_CURSOR: - return "getTextAfterCursor"; - case InputConnectionCommandType.GET_TEXT_BEFORE_CURSOR: - return "getTextBeforeCursor"; - case InputConnectionCommandType.PERFORM_CONTEXT_MENU_ACTION: - return "performContextMenuAction"; - case InputConnectionCommandType.PERFORM_EDITOR_ACTION: - return "performEditorAction"; - case InputConnectionCommandType.PERFORM_SPELL_CHECK: - return "performSpellCheck"; - case InputConnectionCommandType.REQUEST_CURSOR_UPDATES: - return "requestCursorUpdates"; - case InputConnectionCommandType.SEND_KEY_EVENT: - return "sendKeyEvent"; - case InputConnectionCommandType.SET_COMPOSING_REGION: - return "setComposingRegion"; - case InputConnectionCommandType.SET_COMPOSING_TEXT: - return "setComposingText"; - case InputConnectionCommandType.SET_IME_CONSUMES_INPUT: - return "setImeConsumesInput"; - case InputConnectionCommandType.SET_SELECTION: - return "setSelection"; - default: - return "Unknown=" + type; - } - } - - /** - * Converts {@link InputConnectionCommand} to human readable {@link String}. - */ - @NonNull - public static String dumpInputConnectionCommand(@Nullable InputConnectionCommand command) { - if (command == null) { - return "null"; - } - switch (command.mCommandType) { - case InputConnectionCommandType.BEGIN_BATCH_EDIT: - return "beginBatchEdit()"; - case InputConnectionCommandType.CLEAR_META_KEY_STATES: - return "clearMetaKeyStates(" + command.mIntArg0 + ")"; - case InputConnectionCommandType.COMMIT_COMPLETION: - return "commitCompletion(" + command.mParcelable + ")"; - case InputConnectionCommandType.COMMIT_CONTENT: - return "commitContent(" + command.mParcelable + ", " + command.mFlags + ", " - + command.mBundle + ")"; - case InputConnectionCommandType.COMMIT_CORRECTION: - return "commitCorrection(" + command.mParcelable + ")"; - case InputConnectionCommandType.COMMIT_TEXT: - return "commitText(" + command.mCharSequence + ", " + command.mIntArg0 + ")"; - case InputConnectionCommandType.DELETE_SURROUNDING_TEXT: - return "deleteSurroundingText(" + command.mIntArg0 + ", " + command.mIntArg1 + ")"; - case InputConnectionCommandType.DELETE_SURROUNDING_TEXT_IN_CODE_POINTS: - return "deleteSurroundingTextInCodePoints(" + command.mIntArg0 + ", " - + command.mIntArg1 + ")"; - case InputConnectionCommandType.END_BATCH_EDIT: - return "endBatchEdit()"; - case InputConnectionCommandType.FINISH_COMPOSING_TEXT: - return "finishComposingText()"; - case InputConnectionCommandType.GET_CURSOR_CAPS_MODE: - return "getCursorCapsMode(" + command.mIntArg0 + ")"; - case InputConnectionCommandType.GET_EXTRACTED_TEXT: - return "getExtractedText(" + command.mParcelable + ", " + command.mFlags + ")"; - case InputConnectionCommandType.GET_SELECTED_TEXT: - return "getSelectedText(" + command.mFlags + ")"; - case InputConnectionCommandType.GET_SURROUNDING_TEXT: - return "getSurroundingText(" + command.mIntArg0 + ", " + command.mIntArg1 + ", " - + command.mFlags + ")"; - case InputConnectionCommandType.GET_TEXT_AFTER_CURSOR: - return "getTextAfterCursor(" + command.mIntArg0 + ", " + command.mFlags + ")"; - case InputConnectionCommandType.GET_TEXT_BEFORE_CURSOR: - return "getTextBeforeCursor(" + command.mIntArg0 + ", " + command.mFlags + ")"; - case InputConnectionCommandType.PERFORM_CONTEXT_MENU_ACTION: - return "performContextMenuAction(" + command.mIntArg0 + ")"; - case InputConnectionCommandType.PERFORM_EDITOR_ACTION: - return "performEditorAction(" + command.mIntArg0 + ")"; - case InputConnectionCommandType.PERFORM_SPELL_CHECK: - return "performSpellCheck()"; - case InputConnectionCommandType.REQUEST_CURSOR_UPDATES: - return "requestCursorUpdates(" + command.mIntArg0 + ")"; - case InputConnectionCommandType.SEND_KEY_EVENT: - return "sendKeyEvent(" + command.mParcelable + ")"; - case InputConnectionCommandType.SET_COMPOSING_REGION: - return "setComposingRegion(" + command.mIntArg0 + ", " + command.mIntArg1 + ")"; - case InputConnectionCommandType.SET_COMPOSING_TEXT: - return "setComposingText(" + command.mCharSequence + ", " + command.mIntArg0 + ")"; - case InputConnectionCommandType.SET_IME_CONSUMES_INPUT: - return "setImeConsumesInput(" + (command.mIntArg0 != 0) + ")"; - case InputConnectionCommandType.SET_SELECTION: - return "setSelection(" + command.mIntArg0 + ", " + command.mIntArg1 + ")"; - default: - return "unknown(type=" + command.mCommandType + ")"; - } - } - /** * Return a fixed size string of the object. * TODO(b/151575861): Take & return with StringBuilder to make more memory efficient. diff --git a/core/java/com/android/internal/view/IInputConnectionWrapper.java b/core/java/com/android/internal/view/IInputConnectionWrapper.java index fdbbf974ffa1c..46071296d0bf4 100644 --- a/core/java/com/android/internal/view/IInputConnectionWrapper.java +++ b/core/java/com/android/internal/view/IInputConnectionWrapper.java @@ -16,14 +16,13 @@ package com.android.internal.view; -import android.annotation.AnyThread; -import android.annotation.BinderThread; import android.annotation.NonNull; import android.annotation.Nullable; import android.os.Bundle; import android.os.Handler; import android.os.Looper; import android.os.Message; +import android.os.RemoteException; import android.os.Trace; import android.util.Log; import android.util.proto.ProtoOutputStream; @@ -42,12 +41,14 @@ import android.view.inputmethod.InputMethodManager; import android.view.inputmethod.SurroundingText; import com.android.internal.annotations.GuardedBy; -import com.android.internal.inputmethod.CallbackUtils; +import com.android.internal.inputmethod.IBooleanResultCallback; +import com.android.internal.inputmethod.ICharSequenceResultCallback; +import com.android.internal.inputmethod.IExtractedTextResultCallback; +import com.android.internal.inputmethod.IIntResultCallback; +import com.android.internal.inputmethod.ISurroundingTextResultCallback; import com.android.internal.inputmethod.ImeTracing; -import com.android.internal.inputmethod.InputConnectionCommand; -import com.android.internal.inputmethod.InputConnectionCommandType; import com.android.internal.inputmethod.InputConnectionProtoDumper; -import com.android.internal.inputmethod.InputMethodDebug; +import com.android.internal.os.SomeArgs; import java.lang.ref.WeakReference; @@ -55,8 +56,34 @@ public final class IInputConnectionWrapper extends IInputContext.Stub { private static final String TAG = "IInputConnectionWrapper"; private static final boolean DEBUG = false; - private static final int DO_EDIT = 10; - private static final int DO_CLOSE_CONNECTION = 20; + private static final int DO_GET_TEXT_AFTER_CURSOR = 10; + private static final int DO_GET_TEXT_BEFORE_CURSOR = 20; + private static final int DO_GET_SELECTED_TEXT = 25; + private static final int DO_GET_CURSOR_CAPS_MODE = 30; + private static final int DO_GET_EXTRACTED_TEXT = 40; + private static final int DO_COMMIT_TEXT = 50; + private static final int DO_COMMIT_COMPLETION = 55; + private static final int DO_COMMIT_CORRECTION = 56; + private static final int DO_SET_SELECTION = 57; + private static final int DO_PERFORM_EDITOR_ACTION = 58; + private static final int DO_PERFORM_CONTEXT_MENU_ACTION = 59; + private static final int DO_SET_COMPOSING_TEXT = 60; + private static final int DO_SET_COMPOSING_REGION = 63; + private static final int DO_FINISH_COMPOSING_TEXT = 65; + private static final int DO_SEND_KEY_EVENT = 70; + private static final int DO_DELETE_SURROUNDING_TEXT = 80; + private static final int DO_DELETE_SURROUNDING_TEXT_IN_CODE_POINTS = 81; + private static final int DO_BEGIN_BATCH_EDIT = 90; + private static final int DO_END_BATCH_EDIT = 95; + private static final int DO_PERFORM_SPELL_CHECK = 110; + private static final int DO_PERFORM_PRIVATE_COMMAND = 120; + private static final int DO_CLEAR_META_KEY_STATES = 130; + private static final int DO_REQUEST_CURSOR_UPDATES = 140; + private static final int DO_CLOSE_CONNECTION = 150; + private static final int DO_COMMIT_CONTENT = 160; + private static final int DO_GET_SURROUNDING_TEXT = 41; + private static final int DO_SET_IME_CONSUMES_INPUT = 170; + @GuardedBy("mLock") @Nullable @@ -120,7 +147,7 @@ public final class IInputConnectionWrapper extends IInputContext.Stub { // reportFinish() will take effect. return; } - dispatchMessage(mH.obtainMessage(DO_CLOSE_CONNECTION)); + closeConnection(); // Notify the app that the InputConnection was closed. final View servedView = mServedView.get(); @@ -165,33 +192,146 @@ public final class IInputConnectionWrapper extends IInputContext.Stub { } } - @BinderThread - @Override - public void doEdit(@Nullable InputConnectionCommand command) { - if (command == null) { - // As long as everything is working as expected, we should never see any null object - // here. If we are seeing null object, it means that either the sender or - // InputConnectionCommand.CREATOR#createFromParcel() returned null for whatever - // unexpected reasons. Note that InputConnectionCommand.CREATOR#createFromParcel() does - // some data verifications. Hence failing to pass the verification is one of the - // reasons to see null here. - Log.w(TAG, "Ignoring invalid InputConnectionCommand."); - return; - } - if (DEBUG) { - Log.d(TAG, "incoming: " + InputMethodDebug.dumpInputConnectionCommand(command)); - } - dispatchMessage(mH.obtainMessage(DO_EDIT, command)); + public void getTextAfterCursor(int length, int flags, ICharSequenceResultCallback callback) { + dispatchMessage(mH.obtainMessage(DO_GET_TEXT_AFTER_CURSOR, length, flags, callback)); + } + + public void getTextBeforeCursor(int length, int flags, ICharSequenceResultCallback callback) { + dispatchMessage(mH.obtainMessage(DO_GET_TEXT_BEFORE_CURSOR, length, flags, callback)); + } + + public void getSelectedText(int flags, ICharSequenceResultCallback callback) { + dispatchMessage(mH.obtainMessage(DO_GET_SELECTED_TEXT, flags, 0 /* unused */, callback)); } /** - * Exposed for {@link InputMethodManager} to trigger - * {@link InputConnection#finishComposingText()}. + * Dispatches the request for retrieving surrounding text. + * + *

See {@link InputConnection#getSurroundingText(int, int, int)}. */ - @AnyThread + public void getSurroundingText(int beforeLength, int afterLength, int flags, + ISurroundingTextResultCallback callback) { + final SomeArgs args = SomeArgs.obtain(); + args.arg1 = beforeLength; + args.arg2 = afterLength; + args.arg3 = flags; + args.arg4 = callback; + dispatchMessage(mH.obtainMessage(DO_GET_SURROUNDING_TEXT, flags, 0 /* unused */, args)); + } + + public void getCursorCapsMode(int reqModes, IIntResultCallback callback) { + dispatchMessage( + mH.obtainMessage(DO_GET_CURSOR_CAPS_MODE, reqModes, 0 /* unused */, callback)); + } + + public void getExtractedText(ExtractedTextRequest request, int flags, + IExtractedTextResultCallback callback) { + final SomeArgs args = SomeArgs.obtain(); + args.arg1 = request; + args.arg2 = callback; + dispatchMessage(mH.obtainMessage(DO_GET_EXTRACTED_TEXT, flags, 0 /* unused */, args)); + } + + public void commitText(CharSequence text, int newCursorPosition) { + dispatchMessage(obtainMessageIO(DO_COMMIT_TEXT, newCursorPosition, text)); + } + + public void commitCompletion(CompletionInfo text) { + dispatchMessage(obtainMessageO(DO_COMMIT_COMPLETION, text)); + } + + public void commitCorrection(CorrectionInfo info) { + dispatchMessage(obtainMessageO(DO_COMMIT_CORRECTION, info)); + } + + public void setSelection(int start, int end) { + dispatchMessage(obtainMessageII(DO_SET_SELECTION, start, end)); + } + + public void performEditorAction(int id) { + dispatchMessage(obtainMessageII(DO_PERFORM_EDITOR_ACTION, id, 0)); + } + + public void performContextMenuAction(int id) { + dispatchMessage(obtainMessageII(DO_PERFORM_CONTEXT_MENU_ACTION, id, 0)); + } + + public void setComposingRegion(int start, int end) { + dispatchMessage(obtainMessageII(DO_SET_COMPOSING_REGION, start, end)); + } + + public void setComposingText(CharSequence text, int newCursorPosition) { + dispatchMessage(obtainMessageIO(DO_SET_COMPOSING_TEXT, newCursorPosition, text)); + } + public void finishComposingText() { - dispatchMessage(mH.obtainMessage(DO_EDIT, InputConnectionCommand.create( - InputConnectionCommandType.FINISH_COMPOSING_TEXT))); + dispatchMessage(obtainMessage(DO_FINISH_COMPOSING_TEXT)); + } + + public void sendKeyEvent(KeyEvent event) { + dispatchMessage(obtainMessageO(DO_SEND_KEY_EVENT, event)); + } + + public void clearMetaKeyStates(int states) { + dispatchMessage(obtainMessageII(DO_CLEAR_META_KEY_STATES, states, 0)); + } + + public void deleteSurroundingText(int beforeLength, int afterLength) { + dispatchMessage(obtainMessageII(DO_DELETE_SURROUNDING_TEXT, + beforeLength, afterLength)); + } + + public void deleteSurroundingTextInCodePoints(int beforeLength, int afterLength) { + dispatchMessage(obtainMessageII(DO_DELETE_SURROUNDING_TEXT_IN_CODE_POINTS, + beforeLength, afterLength)); + } + + public void beginBatchEdit() { + dispatchMessage(obtainMessage(DO_BEGIN_BATCH_EDIT)); + } + + public void endBatchEdit() { + dispatchMessage(obtainMessage(DO_END_BATCH_EDIT)); + } + + /** + * Dispatches the request for performing spell check. + * + * @see InputConnection#performSpellCheck() + */ + public void performSpellCheck() { + dispatchMessage(obtainMessage(DO_PERFORM_SPELL_CHECK)); + } + + public void performPrivateCommand(String action, Bundle data) { + dispatchMessage(obtainMessageOO(DO_PERFORM_PRIVATE_COMMAND, action, data)); + } + + public void requestCursorUpdates(int cursorUpdateMode, IBooleanResultCallback callback) { + dispatchMessage(mH.obtainMessage(DO_REQUEST_CURSOR_UPDATES, cursorUpdateMode, + 0 /* unused */, callback)); + } + + public void closeConnection() { + dispatchMessage(obtainMessage(DO_CLOSE_CONNECTION)); + } + + public void commitContent(InputContentInfo inputContentInfo, int flags, Bundle opts, + IBooleanResultCallback callback) { + final SomeArgs args = SomeArgs.obtain(); + args.arg1 = inputContentInfo; + args.arg2 = opts; + args.arg3 = callback; + dispatchMessage(mH.obtainMessage(DO_COMMIT_CONTENT, flags, 0 /* unused */, args)); + } + + /** + * Dispatches the request for setting ime consumes input. + * + *

See {@link InputConnection#setImeConsumesInput(boolean)}. + */ + public void setImeConsumesInput(boolean imeConsumesInput) { + dispatchMessage(obtainMessageB(DO_SET_IME_CONSUMES_INPUT, imeConsumesInput)); } void dispatchMessage(Message msg) { @@ -207,131 +347,108 @@ public final class IInputConnectionWrapper extends IInputContext.Stub { mH.sendMessage(msg); } - private void executeMessage(Message msg) { - switch (msg.what) { - case DO_EDIT: - doEditMain((InputConnectionCommand) msg.obj); - break; - case DO_CLOSE_CONNECTION: - // Note that we do not need to worry about race condition here, because 1) mFinished - // is updated only inside this block, and 2) the code here is running on a Handler - // hence we assume multiple DO_CLOSE_CONNECTION messages will not be handled at the - // same time. - if (isFinished()) { - return; - } - Trace.traceBegin(Trace.TRACE_TAG_INPUT, "InputConnection#closeConnection"); - try { - InputConnection ic = getInputConnection(); - // Note we do NOT check isActive() here, because this is safe - // for an IME to call at any time, and we need to allow it - // through to clean up our state after the IME has switched to - // another client. - if (ic == null) { - return; - } - @MissingMethodFlags final int missingMethods = - InputConnectionInspector.getMissingMethodFlags(ic); - if ((missingMethods & MissingMethodFlags.CLOSE_CONNECTION) == 0) { - ic.closeConnection(); - } - } finally { - synchronized (mLock) { - mInputConnection = null; - mFinished = true; - } - Trace.traceEnd(Trace.TRACE_TAG_INPUT); - } - break; - } - } - - private void doEditMain(@NonNull InputConnectionCommand command) { - if (DEBUG) { - Log.d(TAG, "handling: " + InputMethodDebug.dumpInputConnectionCommand(command)); - } + void executeMessage(Message msg) { byte[] icProto; - switch (command.mCommandType) { - case InputConnectionCommandType.GET_TEXT_AFTER_CURSOR: { + switch (msg.what) { + case DO_GET_TEXT_AFTER_CURSOR: { Trace.traceBegin(Trace.TRACE_TAG_INPUT, "InputConnection#getTextAfterCursor"); try { - final int n = command.mIntArg0; - final int flags = command.mFlags; + final ICharSequenceResultCallback callback = + (ICharSequenceResultCallback) msg.obj; final InputConnection ic = getInputConnection(); final CharSequence result; if (ic == null || !isActive()) { Log.w(TAG, "getTextAfterCursor on inactive InputConnection"); result = null; } else { - result = ic.getTextAfterCursor(n, flags); + result = ic.getTextAfterCursor(msg.arg1, msg.arg2); } if (ImeTracing.getInstance().isEnabled()) { - icProto = InputConnectionProtoDumper.buildGetTextAfterCursorProto(n, flags, - result); + icProto = InputConnectionProtoDumper.buildGetTextAfterCursorProto(msg.arg1, + msg.arg2, result); ImeTracing.getInstance().triggerClientDump( TAG + "#getTextAfterCursor", mParentInputMethodManager, icProto); } - CallbackUtils.onResult(command, result, TAG); + try { + callback.onResult(result); + } catch (RemoteException e) { + Log.w(TAG, "Failed to return the result to getTextAfterCursor()." + + " result=" + result, e); + } } finally { Trace.traceEnd(Trace.TRACE_TAG_INPUT); } return; } - case InputConnectionCommandType.GET_TEXT_BEFORE_CURSOR: { + case DO_GET_TEXT_BEFORE_CURSOR: { Trace.traceBegin(Trace.TRACE_TAG_INPUT, "InputConnection#getTextBeforeCursor"); try { - final int n = command.mIntArg0; - final int flags = command.mFlags; + final ICharSequenceResultCallback callback = + (ICharSequenceResultCallback) msg.obj; final InputConnection ic = getInputConnection(); final CharSequence result; if (ic == null || !isActive()) { Log.w(TAG, "getTextBeforeCursor on inactive InputConnection"); result = null; } else { - result = ic.getTextBeforeCursor(n, flags); + result = ic.getTextBeforeCursor(msg.arg1, msg.arg2); } if (ImeTracing.getInstance().isEnabled()) { - icProto = InputConnectionProtoDumper.buildGetTextBeforeCursorProto(n, flags, - result); + icProto = InputConnectionProtoDumper.buildGetTextBeforeCursorProto(msg.arg1, + msg.arg2, result); ImeTracing.getInstance().triggerClientDump( TAG + "#getTextBeforeCursor", mParentInputMethodManager, icProto); } - CallbackUtils.onResult(command, result, TAG); + try { + callback.onResult(result); + } catch (RemoteException e) { + Log.w(TAG, "Failed to return the result to getTextBeforeCursor()." + + " result=" + result, e); + } } finally { Trace.traceEnd(Trace.TRACE_TAG_INPUT); } return; } - case InputConnectionCommandType.GET_SELECTED_TEXT: { + case DO_GET_SELECTED_TEXT: { Trace.traceBegin(Trace.TRACE_TAG_INPUT, "InputConnection#getSelectedText"); try { - final int flags = command.mFlags; + final ICharSequenceResultCallback callback = + (ICharSequenceResultCallback) msg.obj; final InputConnection ic = getInputConnection(); final CharSequence result; if (ic == null || !isActive()) { Log.w(TAG, "getSelectedText on inactive InputConnection"); result = null; } else { - result = ic.getSelectedText(flags); + result = ic.getSelectedText(msg.arg1); } if (ImeTracing.getInstance().isEnabled()) { - icProto = InputConnectionProtoDumper.buildGetSelectedTextProto(flags, + icProto = InputConnectionProtoDumper.buildGetSelectedTextProto(msg.arg1, result); ImeTracing.getInstance().triggerClientDump( TAG + "#getSelectedText", mParentInputMethodManager, icProto); } - CallbackUtils.onResult(command, result, TAG); + try { + callback.onResult(result); + } catch (RemoteException e) { + Log.w(TAG, "Failed to return the result to getSelectedText()." + + " result=" + result, e); + } } finally { Trace.traceEnd(Trace.TRACE_TAG_INPUT); } return; } - case InputConnectionCommandType.GET_SURROUNDING_TEXT: { + case DO_GET_SURROUNDING_TEXT: { + final SomeArgs args = (SomeArgs) msg.obj; Trace.traceBegin(Trace.TRACE_TAG_INPUT, "InputConnection#getSurroundingText"); try { - final int beforeLength = command.mIntArg0; - final int afterLength = command.mIntArg1; - final int flags = command.mFlags; + int beforeLength = (int) args.arg1; + int afterLength = (int) args.arg2; + int flags = (int) args.arg3; + final ISurroundingTextResultCallback callback = + (ISurroundingTextResultCallback) args.arg4; final InputConnection ic = getInputConnection(); final SurroundingText result; if (ic == null || !isActive()) { @@ -346,186 +463,193 @@ public final class IInputConnectionWrapper extends IInputContext.Stub { ImeTracing.getInstance().triggerClientDump( TAG + "#getSurroundingText", mParentInputMethodManager, icProto); } - CallbackUtils.onResult(command, result, TAG); + try { + callback.onResult(result); + } catch (RemoteException e) { + Log.w(TAG, "Failed to return the result to getSurroundingText()." + + " result=" + result, e); + } } finally { Trace.traceEnd(Trace.TRACE_TAG_INPUT); + args.recycle(); } return; } - case InputConnectionCommandType.GET_CURSOR_CAPS_MODE: { + case DO_GET_CURSOR_CAPS_MODE: { Trace.traceBegin(Trace.TRACE_TAG_INPUT, "InputConnection#getCursorCapsMode"); try { - final int reqModes = command.mIntArg0; + final IIntResultCallback callback = (IIntResultCallback) msg.obj; final InputConnection ic = getInputConnection(); final int result; if (ic == null || !isActive()) { Log.w(TAG, "getCursorCapsMode on inactive InputConnection"); result = 0; } else { - result = ic.getCursorCapsMode(reqModes); + result = ic.getCursorCapsMode(msg.arg1); } if (ImeTracing.getInstance().isEnabled()) { - icProto = InputConnectionProtoDumper.buildGetCursorCapsModeProto(reqModes, + icProto = InputConnectionProtoDumper.buildGetCursorCapsModeProto(msg.arg1, result); ImeTracing.getInstance().triggerClientDump( TAG + "#getCursorCapsMode", mParentInputMethodManager, icProto); } - CallbackUtils.onResult(command, result, TAG); + try { + callback.onResult(result); + } catch (RemoteException e) { + Log.w(TAG, "Failed to return the result to getCursorCapsMode()." + + " result=" + result, e); + } } finally { Trace.traceEnd(Trace.TRACE_TAG_INPUT); } return; } - case InputConnectionCommandType.GET_EXTRACTED_TEXT: { + case DO_GET_EXTRACTED_TEXT: { + final SomeArgs args = (SomeArgs) msg.obj; Trace.traceBegin(Trace.TRACE_TAG_INPUT, "InputConnection#getExtractedText"); try { - final ExtractedTextRequest request = (ExtractedTextRequest) command.mParcelable; - final int flags = command.mFlags; + final ExtractedTextRequest request = (ExtractedTextRequest) args.arg1; + final IExtractedTextResultCallback callback = + (IExtractedTextResultCallback) args.arg2; final InputConnection ic = getInputConnection(); final ExtractedText result; if (ic == null || !isActive()) { Log.w(TAG, "getExtractedText on inactive InputConnection"); result = null; } else { - result = ic.getExtractedText(request, flags); + result = ic.getExtractedText(request, msg.arg1); } if (ImeTracing.getInstance().isEnabled()) { icProto = InputConnectionProtoDumper.buildGetExtractedTextProto(request, - flags, result); + msg.arg1, result); ImeTracing.getInstance().triggerClientDump( TAG + "#getExtractedText", mParentInputMethodManager, icProto); } - CallbackUtils.onResult(command, result, TAG); + try { + callback.onResult(result); + } catch (RemoteException e) { + Log.w(TAG, "Failed to return the result to getExtractedText()." + + " result=" + result, e); + } } finally { Trace.traceEnd(Trace.TRACE_TAG_INPUT); + args.recycle(); } return; } - case InputConnectionCommandType.COMMIT_TEXT: { + case DO_COMMIT_TEXT: { Trace.traceBegin(Trace.TRACE_TAG_INPUT, "InputConnection#commitText"); try { - final CharSequence text = command.mCharSequence; - final int newCursorPosition = command.mIntArg0; InputConnection ic = getInputConnection(); if (ic == null || !isActive()) { Log.w(TAG, "commitText on inactive InputConnection"); return; } - ic.commitText(text, newCursorPosition); + ic.commitText((CharSequence) msg.obj, msg.arg1); } finally { Trace.traceEnd(Trace.TRACE_TAG_INPUT); } return; } - case InputConnectionCommandType.SET_SELECTION: { + case DO_SET_SELECTION: { Trace.traceBegin(Trace.TRACE_TAG_INPUT, "InputConnection#setSelection"); try { - final int start = command.mIntArg0; - final int end = command.mIntArg1; InputConnection ic = getInputConnection(); if (ic == null || !isActive()) { Log.w(TAG, "setSelection on inactive InputConnection"); return; } - ic.setSelection(start, end); + ic.setSelection(msg.arg1, msg.arg2); } finally { Trace.traceEnd(Trace.TRACE_TAG_INPUT); } return; } - case InputConnectionCommandType.PERFORM_EDITOR_ACTION: { + case DO_PERFORM_EDITOR_ACTION: { Trace.traceBegin(Trace.TRACE_TAG_INPUT, "InputConnection#performEditorAction"); try { - final int editorAction = command.mIntArg0; InputConnection ic = getInputConnection(); if (ic == null || !isActive()) { Log.w(TAG, "performEditorAction on inactive InputConnection"); return; } - ic.performEditorAction(editorAction); + ic.performEditorAction(msg.arg1); } finally { Trace.traceEnd(Trace.TRACE_TAG_INPUT); } return; } - case InputConnectionCommandType.PERFORM_CONTEXT_MENU_ACTION: { + case DO_PERFORM_CONTEXT_MENU_ACTION: { Trace.traceBegin(Trace.TRACE_TAG_INPUT, "InputConnection#performContextMenuAction"); try { - final int id = command.mIntArg0; InputConnection ic = getInputConnection(); if (ic == null || !isActive()) { Log.w(TAG, "performContextMenuAction on inactive InputConnection"); return; } - ic.performContextMenuAction(id); + ic.performContextMenuAction(msg.arg1); } finally { Trace.traceEnd(Trace.TRACE_TAG_INPUT); } return; } - case InputConnectionCommandType.COMMIT_COMPLETION: { + case DO_COMMIT_COMPLETION: { Trace.traceBegin(Trace.TRACE_TAG_INPUT, "InputConnection#commitCompletion"); try { - final CompletionInfo text = (CompletionInfo) command.mParcelable; InputConnection ic = getInputConnection(); if (ic == null || !isActive()) { Log.w(TAG, "commitCompletion on inactive InputConnection"); return; } - ic.commitCompletion(text); + ic.commitCompletion((CompletionInfo) msg.obj); } finally { Trace.traceEnd(Trace.TRACE_TAG_INPUT); } return; } - case InputConnectionCommandType.COMMIT_CORRECTION: { + case DO_COMMIT_CORRECTION: { Trace.traceBegin(Trace.TRACE_TAG_INPUT, "InputConnection#commitCorrection"); try { - final CorrectionInfo correctionInfo = (CorrectionInfo) command.mParcelable; InputConnection ic = getInputConnection(); if (ic == null || !isActive()) { Log.w(TAG, "commitCorrection on inactive InputConnection"); return; } - ic.commitCorrection(correctionInfo); + ic.commitCorrection((CorrectionInfo) msg.obj); } finally { Trace.traceEnd(Trace.TRACE_TAG_INPUT); } return; } - case InputConnectionCommandType.SET_COMPOSING_TEXT: { + case DO_SET_COMPOSING_TEXT: { Trace.traceBegin(Trace.TRACE_TAG_INPUT, "InputConnection#setComposingText"); try { - final CharSequence text = command.mCharSequence; - final int newCursorPosition = command.mIntArg0; InputConnection ic = getInputConnection(); if (ic == null || !isActive()) { Log.w(TAG, "setComposingText on inactive InputConnection"); return; } - ic.setComposingText(text, newCursorPosition); + ic.setComposingText((CharSequence) msg.obj, msg.arg1); } finally { Trace.traceEnd(Trace.TRACE_TAG_INPUT); } return; } - case InputConnectionCommandType.SET_COMPOSING_REGION: { + case DO_SET_COMPOSING_REGION: { Trace.traceBegin(Trace.TRACE_TAG_INPUT, "InputConnection#setComposingRegion"); try { - final int start = command.mIntArg0; - final int end = command.mIntArg1; InputConnection ic = getInputConnection(); if (ic == null || !isActive()) { Log.w(TAG, "setComposingRegion on inactive InputConnection"); return; } - ic.setComposingRegion(start, end); + ic.setComposingRegion(msg.arg1, msg.arg2); } finally { Trace.traceEnd(Trace.TRACE_TAG_INPUT); } return; } - case InputConnectionCommandType.FINISH_COMPOSING_TEXT: { + case DO_FINISH_COMPOSING_TEXT: { Trace.traceBegin(Trace.TRACE_TAG_INPUT, "InputConnection#finishComposingText"); try { if (isFinished()) { @@ -551,70 +675,64 @@ public final class IInputConnectionWrapper extends IInputContext.Stub { } return; } - case InputConnectionCommandType.SEND_KEY_EVENT: { + case DO_SEND_KEY_EVENT: { Trace.traceBegin(Trace.TRACE_TAG_INPUT, "InputConnection#sendKeyEvent"); try { - final KeyEvent event = (KeyEvent) command.mParcelable; InputConnection ic = getInputConnection(); if (ic == null || !isActive()) { Log.w(TAG, "sendKeyEvent on inactive InputConnection"); return; } - ic.sendKeyEvent(event); + ic.sendKeyEvent((KeyEvent) msg.obj); } finally { Trace.traceEnd(Trace.TRACE_TAG_INPUT); } return; } - case InputConnectionCommandType.CLEAR_META_KEY_STATES: { + case DO_CLEAR_META_KEY_STATES: { Trace.traceBegin(Trace.TRACE_TAG_INPUT, "InputConnection#clearMetaKeyStates"); try { - final int states = command.mIntArg0; InputConnection ic = getInputConnection(); if (ic == null || !isActive()) { Log.w(TAG, "clearMetaKeyStates on inactive InputConnection"); return; } - ic.clearMetaKeyStates(states); + ic.clearMetaKeyStates(msg.arg1); } finally { Trace.traceEnd(Trace.TRACE_TAG_INPUT); } return; } - case InputConnectionCommandType.DELETE_SURROUNDING_TEXT: { + case DO_DELETE_SURROUNDING_TEXT: { Trace.traceBegin(Trace.TRACE_TAG_INPUT, "InputConnection#deleteSurroundingText"); try { - final int beforeLength = command.mIntArg0; - final int afterLength = command.mIntArg1; InputConnection ic = getInputConnection(); if (ic == null || !isActive()) { Log.w(TAG, "deleteSurroundingText on inactive InputConnection"); return; } - ic.deleteSurroundingText(beforeLength, afterLength); + ic.deleteSurroundingText(msg.arg1, msg.arg2); } finally { Trace.traceEnd(Trace.TRACE_TAG_INPUT); } return; } - case InputConnectionCommandType.DELETE_SURROUNDING_TEXT_IN_CODE_POINTS: { + case DO_DELETE_SURROUNDING_TEXT_IN_CODE_POINTS: { Trace.traceBegin(Trace.TRACE_TAG_INPUT, "InputConnection#deleteSurroundingTextInCodePoints"); try { - final int beforeLength = command.mIntArg0; - final int afterLength = command.mIntArg1; InputConnection ic = getInputConnection(); if (ic == null || !isActive()) { Log.w(TAG, "deleteSurroundingTextInCodePoints on inactive InputConnection"); return; } - ic.deleteSurroundingTextInCodePoints(beforeLength, afterLength); + ic.deleteSurroundingTextInCodePoints(msg.arg1, msg.arg2); } finally { Trace.traceEnd(Trace.TRACE_TAG_INPUT); } return; } - case InputConnectionCommandType.BEGIN_BATCH_EDIT: { + case DO_BEGIN_BATCH_EDIT: { Trace.traceBegin(Trace.TRACE_TAG_INPUT, "InputConnection#beginBatchEdit"); try { InputConnection ic = getInputConnection(); @@ -628,7 +746,7 @@ public final class IInputConnectionWrapper extends IInputContext.Stub { } return; } - case InputConnectionCommandType.END_BATCH_EDIT: { + case DO_END_BATCH_EDIT: { Trace.traceBegin(Trace.TRACE_TAG_INPUT, "InputConnection#endBatchEdit"); try { InputConnection ic = getInputConnection(); @@ -642,7 +760,7 @@ public final class IInputConnectionWrapper extends IInputContext.Stub { } return; } - case InputConnectionCommandType.PERFORM_SPELL_CHECK: { + case DO_PERFORM_SPELL_CHECK: { Trace.traceBegin(Trace.TRACE_TAG_INPUT, "InputConnection#performSpellCheck"); try { InputConnection ic = getInputConnection(); @@ -656,11 +774,12 @@ public final class IInputConnectionWrapper extends IInputContext.Stub { } return; } - case InputConnectionCommandType.PERFORM_PRIVATE_COMMAND: { + case DO_PERFORM_PRIVATE_COMMAND: { + final SomeArgs args = (SomeArgs) msg.obj; Trace.traceBegin(Trace.TRACE_TAG_INPUT, "InputConnection#performPrivateCommand"); try { - final String action = command.mString; - final Bundle data = command.mBundle; + final String action = (String) args.arg1; + final Bundle data = (Bundle) args.arg2; InputConnection ic = getInputConnection(); if (ic == null || !isActive()) { Log.w(TAG, "performPrivateCommand on inactive InputConnection"); @@ -669,71 +788,142 @@ public final class IInputConnectionWrapper extends IInputContext.Stub { ic.performPrivateCommand(action, data); } finally { Trace.traceEnd(Trace.TRACE_TAG_INPUT); + args.recycle(); } return; } - case InputConnectionCommandType.REQUEST_CURSOR_UPDATES: { + case DO_REQUEST_CURSOR_UPDATES: { Trace.traceBegin(Trace.TRACE_TAG_INPUT, "InputConnection#requestCursorUpdates"); try { - final int cursorUpdateMode = command.mIntArg0; + final IBooleanResultCallback callback = (IBooleanResultCallback) msg.obj; final InputConnection ic = getInputConnection(); final boolean result; if (ic == null || !isActive()) { Log.w(TAG, "requestCursorAnchorInfo on inactive InputConnection"); result = false; } else { - result = ic.requestCursorUpdates(cursorUpdateMode); + result = ic.requestCursorUpdates(msg.arg1); + } + try { + callback.onResult(result); + } catch (RemoteException e) { + Log.w(TAG, "Failed to return the result to requestCursorUpdates()." + + " result=" + result, e); } - CallbackUtils.onResult(command, result, TAG); } finally { Trace.traceEnd(Trace.TRACE_TAG_INPUT); } return; } - case InputConnectionCommandType.COMMIT_CONTENT: { + case DO_CLOSE_CONNECTION: { + // Note that we do not need to worry about race condition here, because 1) mFinished + // is updated only inside this block, and 2) the code here is running on a Handler + // hence we assume multiple DO_CLOSE_CONNECTION messages will not be handled at the + // same time. + if (isFinished()) { + return; + } + Trace.traceBegin(Trace.TRACE_TAG_INPUT, "InputConnection#closeConnection"); + try { + InputConnection ic = getInputConnection(); + // Note we do NOT check isActive() here, because this is safe + // for an IME to call at any time, and we need to allow it + // through to clean up our state after the IME has switched to + // another client. + if (ic == null) { + return; + } + @MissingMethodFlags + final int missingMethods = InputConnectionInspector.getMissingMethodFlags(ic); + if ((missingMethods & MissingMethodFlags.CLOSE_CONNECTION) == 0) { + ic.closeConnection(); + } + } finally { + synchronized (mLock) { + mInputConnection = null; + mFinished = true; + } + Trace.traceEnd(Trace.TRACE_TAG_INPUT); + } + return; + } + case DO_COMMIT_CONTENT: { + final int flags = msg.arg1; + SomeArgs args = (SomeArgs) msg.obj; Trace.traceBegin(Trace.TRACE_TAG_INPUT, "InputConnection#commitContent"); try { - final InputContentInfo inputContentInfo = - (InputContentInfo) command.mParcelable; - final int flags = command.mFlags; - final Bundle opts = command.mBundle; + final IBooleanResultCallback callback = (IBooleanResultCallback) args.arg3; final InputConnection ic = getInputConnection(); final boolean result; if (ic == null || !isActive()) { Log.w(TAG, "commitContent on inactive InputConnection"); result = false; } else { + final InputContentInfo inputContentInfo = (InputContentInfo) args.arg1; if (inputContentInfo == null || !inputContentInfo.validate()) { Log.w(TAG, "commitContent with invalid inputContentInfo=" + inputContentInfo); result = false; } else { - result = ic.commitContent(inputContentInfo, flags, opts); + result = ic.commitContent(inputContentInfo, flags, (Bundle) args.arg2); } } - CallbackUtils.onResult(command, result, TAG); + try { + callback.onResult(result); + } catch (RemoteException e) { + Log.w(TAG, "Failed to return the result to commitContent()." + + " result=" + result, e); + } } finally { Trace.traceEnd(Trace.TRACE_TAG_INPUT); + args.recycle(); } return; } - case InputConnectionCommandType.SET_IME_CONSUMES_INPUT: { + case DO_SET_IME_CONSUMES_INPUT: { Trace.traceBegin(Trace.TRACE_TAG_INPUT, "InputConnection#setImeConsumesInput"); try { - final boolean imeConsumesInput = (command.mIntArg0 != 0); InputConnection ic = getInputConnection(); if (ic == null || !isActive()) { Log.w(TAG, "setImeConsumesInput on inactive InputConnection"); return; } - ic.setImeConsumesInput(imeConsumesInput); + ic.setImeConsumesInput(msg.arg1 == 1); } finally { Trace.traceEnd(Trace.TRACE_TAG_INPUT); } return; } } + Log.w(TAG, "Unhandled message code: " + msg.what); + } + + Message obtainMessage(int what) { + return mH.obtainMessage(what); + } + + Message obtainMessageII(int what, int arg1, int arg2) { + return mH.obtainMessage(what, arg1, arg2); + } + + Message obtainMessageO(int what, Object arg1) { + return mH.obtainMessage(what, 0, 0, arg1); + } + + Message obtainMessageIO(int what, int arg1, Object arg2) { + return mH.obtainMessage(what, arg1, 0, arg2); + } + + Message obtainMessageOO(int what, Object arg1, Object arg2) { + final SomeArgs args = SomeArgs.obtain(); + args.arg1 = arg1; + args.arg2 = arg2; + return mH.obtainMessage(what, 0, 0, args); + } + + Message obtainMessageB(int what, boolean arg1) { + return mH.obtainMessage(what, arg1 ? 1 : 0, 0); } } diff --git a/core/java/com/android/internal/view/IInputContext.aidl b/core/java/com/android/internal/view/IInputContext.aidl index 095c0b42e008f..dd42c40edb493 100644 --- a/core/java/com/android/internal/view/IInputContext.aidl +++ b/core/java/com/android/internal/view/IInputContext.aidl @@ -16,13 +16,76 @@ package com.android.internal.view; -import com.android.internal.inputmethod.InputConnectionCommand; +import android.os.Bundle; +import android.view.KeyEvent; +import android.view.inputmethod.CompletionInfo; +import android.view.inputmethod.CorrectionInfo; +import android.view.inputmethod.ExtractedTextRequest; +import android.view.inputmethod.InputContentInfo; + +import com.android.internal.inputmethod.IBooleanResultCallback; +import com.android.internal.inputmethod.ICharSequenceResultCallback; +import com.android.internal.inputmethod.IExtractedTextResultCallback; +import com.android.internal.inputmethod.IIntResultCallback; +import com.android.internal.inputmethod.ISurroundingTextResultCallback; /** * Interface from an input method to the application, allowing it to perform * edits on the current input field and other interactions with the application. * {@hide} */ -oneway interface IInputContext { - void doEdit(in InputConnectionCommand command); + oneway interface IInputContext { + void getTextBeforeCursor(int length, int flags, ICharSequenceResultCallback callback); + + void getTextAfterCursor(int length, int flags, ICharSequenceResultCallback callback); + + void getCursorCapsMode(int reqModes, IIntResultCallback callback); + + void getExtractedText(in ExtractedTextRequest request, int flags, + IExtractedTextResultCallback callback); + + void deleteSurroundingText(int beforeLength, int afterLength); + void deleteSurroundingTextInCodePoints(int beforeLength, int afterLength); + + void setComposingText(CharSequence text, int newCursorPosition); + + void finishComposingText(); + + void commitText(CharSequence text, int newCursorPosition); + + void commitCompletion(in CompletionInfo completion); + + void commitCorrection(in CorrectionInfo correction); + + void setSelection(int start, int end); + + void performEditorAction(int actionCode); + + void performContextMenuAction(int id); + + void beginBatchEdit(); + + void endBatchEdit(); + + void sendKeyEvent(in KeyEvent event); + + void clearMetaKeyStates(int states); + + void performSpellCheck(); + + void performPrivateCommand(String action, in Bundle data); + + void setComposingRegion(int start, int end); + + void getSelectedText(int flags, ICharSequenceResultCallback callback); + + void requestCursorUpdates(int cursorUpdateMode, IBooleanResultCallback callback); + + void commitContent(in InputContentInfo inputContentInfo, int flags, in Bundle opts, + IBooleanResultCallback callback); + + void getSurroundingText(int beforeLength, int afterLength, int flags, + ISurroundingTextResultCallback callback); + + void setImeConsumesInput(boolean imeConsumesInput); } diff --git a/core/tests/coretests/src/com/android/internal/inputmethod/InputMethodDebugTest.java b/core/tests/coretests/src/com/android/internal/inputmethod/InputMethodDebugTest.java index 9de09d6632cd4..32bfdcb7b2174 100644 --- a/core/tests/coretests/src/com/android/internal/inputmethod/InputMethodDebugTest.java +++ b/core/tests/coretests/src/com/android/internal/inputmethod/InputMethodDebugTest.java @@ -73,13 +73,4 @@ public class InputMethodDebugTest { InputMethodDebug.softInputDisplayReasonToString( SoftInputShowHideReason.HIDE_REMOVE_CLIENT)); } - - @Test - public void testDumpInputConnectionCommand() { - // TODO: add more tests - assertEquals("null", InputMethodDebug.dumpInputConnectionCommand(null)); - assertEquals("endBatchEdit()", - InputMethodDebug.dumpInputConnectionCommand( - InputConnectionCommand.create(InputConnectionCommandType.END_BATCH_EDIT))); - } }