Introduce IInputMethodManager.StartInputParams

IInputMethod#startInput() is a hot-spot where we keep adding new
parameters recently.  Introducing a dedicated parameter object would
allow us to add further parameters with fewer lines of changes.

This CL also renames

  InputMethod#dispatchStartInputWithToken

to

  InputMethod#dispatchStartInput

for consistency.

This is a mechanical refactoring. There should be no developer
observable behavior change.

Bug: 234882948
Test: presubmit
Change-Id: I4a6af9a47db04335921a7d14efe91bfeff25c56d
This commit is contained in:
Yohei Yukawa
2022-06-29 12:09:22 -07:00
parent 55b543e1e8
commit bb00fe959a
5 changed files with 54 additions and 76 deletions

View File

@@ -31,13 +31,11 @@ import android.os.ResultReceiver;
import android.util.Log;
import android.view.InputChannel;
import android.view.MotionEvent;
import android.view.inputmethod.EditorInfo;
import android.view.inputmethod.InputBinding;
import android.view.inputmethod.InputConnection;
import android.view.inputmethod.InputMethod;
import android.view.inputmethod.InputMethodSession;
import android.view.inputmethod.InputMethodSubtype;
import android.window.ImeOnBackInvokedDispatcher;
import com.android.internal.inputmethod.CancellationGroup;
import com.android.internal.inputmethod.IInlineSuggestionsRequestCallback;
@@ -98,9 +96,9 @@ class IInputMethodWrapper extends IInputMethod.Stub
*
* <p>This field must be set and cleared only from the binder thread(s), where the system
* guarantees that {@link #bindInput(InputBinding)},
* {@link #startInput(IBinder, IRemoteInputConnection, int, EditorInfo, boolean, boolean)}, and
* {@link #unbindInput()} are called with the same order as the original calls
* in {@link com.android.server.inputmethod.InputMethodManagerService}.
* {@link #startInput(IInputMethod.StartInputParams)}, and {@link #unbindInput()} are called
* with the same order as the original calls in
* {@link com.android.server.inputmethod.InputMethodManagerService}.
* See {@link IBinder#FLAG_ONEWAY} for detailed semantics.</p>
*/
@Nullable
@@ -194,16 +192,10 @@ class IInputMethodWrapper extends IInputMethod.Stub
return;
case DO_START_INPUT: {
final SomeArgs args = (SomeArgs) msg.obj;
final IBinder startInputToken = (IBinder) args.arg1;
final InputConnection ic = (InputConnection) args.arg2;
final EditorInfo info = (EditorInfo) args.arg3;
final ImeOnBackInvokedDispatcher imeDispatcher =
(ImeOnBackInvokedDispatcher) args.arg4;
final boolean restarting = args.argi1 == 1;
@InputMethodNavButtonFlags
final int navButtonFlags = args.argi2;
inputMethod.dispatchStartInputWithToken(ic, info, restarting, startInputToken,
navButtonFlags, imeDispatcher);
final InputConnection inputConnection = (InputConnection) args.arg1;
final IInputMethod.StartInputParams params =
(IInputMethod.StartInputParams) args.arg2;
inputMethod.dispatchStartInput(inputConnection, params);
args.recycle();
return;
}
@@ -345,28 +337,19 @@ class IInputMethodWrapper extends IInputMethod.Stub
@BinderThread
@Override
public void startInput(IBinder startInputToken, IRemoteInputConnection inputConnection,
EditorInfo editorInfo, boolean restarting,
@InputMethodNavButtonFlags int navButtonFlags,
@NonNull ImeOnBackInvokedDispatcher imeDispatcher) {
public void startInput(@NonNull IInputMethod.StartInputParams params) {
if (mCancellationGroup == null) {
Log.e(TAG, "startInput must be called after bindInput.");
mCancellationGroup = new CancellationGroup();
}
editorInfo.makeCompatible(mTargetSdkVersion);
params.editorInfo.makeCompatible(mTargetSdkVersion);
final InputConnection ic = inputConnection == null ? null
: new RemoteInputConnection(mTarget, inputConnection, mCancellationGroup);
final InputConnection ic = params.remoteInputConnection == null ? null
: new RemoteInputConnection(mTarget, params.remoteInputConnection,
mCancellationGroup);
final SomeArgs args = SomeArgs.obtain();
args.arg1 = startInputToken;
args.arg2 = ic;
args.arg3 = editorInfo;
args.argi1 = restarting ? 1 : 0;
args.argi2 = navButtonFlags;
args.arg4 = imeDispatcher;
mCaller.executeOrSendMessage(mCaller.obtainMessageO(DO_START_INPUT, args));
mCaller.executeOrSendMessage(mCaller.obtainMessageOO(DO_START_INPUT, ic, params));
}
@BinderThread

View File

@@ -144,6 +144,7 @@ import android.window.WindowMetricsHelper;
import com.android.internal.annotations.GuardedBy;
import com.android.internal.inputmethod.IInlineSuggestionsRequestCallback;
import com.android.internal.inputmethod.IInputContentUriToken;
import com.android.internal.inputmethod.IInputMethod;
import com.android.internal.inputmethod.IInputMethodPrivilegedOperations;
import com.android.internal.inputmethod.IRemoteInputConnection;
import com.android.internal.inputmethod.ImeTracing;
@@ -821,25 +822,23 @@ public class InputMethodService extends AbstractInputMethodService {
*/
@MainThread
@Override
public final void dispatchStartInputWithToken(@Nullable InputConnection inputConnection,
@NonNull EditorInfo editorInfo, boolean restarting,
@NonNull IBinder startInputToken, @InputMethodNavButtonFlags int navButtonFlags,
@NonNull ImeOnBackInvokedDispatcher imeDispatcher) {
mPrivOps.reportStartInputAsync(startInputToken);
mNavigationBarController.onNavButtonFlagsChanged(navButtonFlags);
if (restarting) {
restartInput(inputConnection, editorInfo);
public final void dispatchStartInput(@Nullable InputConnection inputConnection,
@NonNull IInputMethod.StartInputParams params) {
mPrivOps.reportStartInputAsync(params.startInputToken);
mNavigationBarController.onNavButtonFlagsChanged(params.navigationBarFlags);
if (params.restarting) {
restartInput(inputConnection, params.editorInfo);
} else {
startInput(inputConnection, editorInfo);
startInput(inputConnection, params.editorInfo);
}
// Update the IME dispatcher last, so that the previously registered back callback
// (if any) can be unregistered using the old dispatcher if {@link #doFinishInput()}
// is called from {@link #startInput(InputConnection, EditorInfo)} or
// {@link #restartInput(InputConnection, EditorInfo)}.
mImeDispatcher = imeDispatcher;
mImeDispatcher = params.imeDispatcher;
if (mWindow != null) {
mWindow.getOnBackInvokedDispatcher().setImeOnBackInvokedDispatcher(
imeDispatcher);
params.imeDispatcher);
}
}

View File

@@ -29,9 +29,9 @@ import android.util.Log;
import android.view.InputChannel;
import android.view.MotionEvent;
import android.view.View;
import android.window.ImeOnBackInvokedDispatcher;
import com.android.internal.inputmethod.IInlineSuggestionsRequestCallback;
import com.android.internal.inputmethod.IInputMethod;
import com.android.internal.inputmethod.IInputMethodPrivilegedOperations;
import com.android.internal.inputmethod.InlineSuggestionsRequestInfo;
import com.android.internal.inputmethod.InputMethodNavButtonFlags;
@@ -210,47 +210,30 @@ public interface InputMethod {
public void restartInput(InputConnection inputConnection, EditorInfo editorInfo);
/**
* This method is called when {@code {@link #startInput(InputConnection, EditorInfo)} or
* {@code {@link #restartInput(InputConnection, EditorInfo)} needs to be dispatched.
* This method is called when {@link #startInput(InputConnection, EditorInfo)} or
* {@link #restartInput(InputConnection, EditorInfo)} needs to be dispatched.
*
* <p>Note: This method is hidden because the {@code startInputToken} that this method is
* dealing with is one of internal details, which should not be exposed to the IME developers.
* If you override this method, you are responsible for not breaking existing IMEs that expect
* <p>Note: This method is hidden because {@link IInputMethod.StartInputParams} is an internal
* details, which should not be exposed to the IME developers. If you override this method, you
* are responsible for not breaking existing IMEs that expect
* {@link #startInput(InputConnection, EditorInfo)} to be still called back.</p>
*
* @param inputConnection optional specific input connection for communicating with the text
* box; if {@code null}, you should use the generic bound input
* connection
* @param editorInfo information about the text box (typically, an EditText) that requests input
* @param restarting {@code false} if this corresponds to
* {@link #startInput(InputConnection, EditorInfo)}. Otherwise this
* corresponds to {@link #restartInput(InputConnection, EditorInfo)}.
* @param startInputToken a token that identifies a logical session that starts with this method
* call. Some internal IPCs such as {@link
* InputMethodManager#setImeWindowStatus(IBinder, IBinder, int, int)}
* require this token to work, and you have to keep the token alive until
* the next {@link #startInput(InputConnection, EditorInfo, IBinder)} as
* long as your implementation of {@link InputMethod} relies on such
* IPCs
* @param navButtonFlags {@link InputMethodNavButtonFlags} in the initial state of this session.
* @param imeDispatcher The {@link ImeOnBackInvokedDispatcher} to be set on the
* IME's {@link android.window.WindowOnBackInvokedDispatcher}, so that IME
* {@link android.window.OnBackInvokedCallback}s can be forwarded to
* the client requesting to start input.
* @param params Raw object of {@link IInputMethod.StartInputParams}.
* @see #startInput(InputConnection, EditorInfo)
* @see #restartInput(InputConnection, EditorInfo)
* @see EditorInfo
* @hide
*/
@MainThread
default void dispatchStartInputWithToken(@Nullable InputConnection inputConnection,
@NonNull EditorInfo editorInfo, boolean restarting,
@NonNull IBinder startInputToken, @InputMethodNavButtonFlags int navButtonFlags,
@NonNull ImeOnBackInvokedDispatcher imeDispatcher) {
if (restarting) {
restartInput(inputConnection, editorInfo);
default void dispatchStartInput(@Nullable InputConnection inputConnection,
@NonNull IInputMethod.StartInputParams params) {
if (params.restarting) {
restartInput(inputConnection, params.editorInfo);
} else {
startInput(inputConnection, editorInfo);
startInput(inputConnection, params.editorInfo);
}
}

View File

@@ -45,9 +45,16 @@ oneway interface IInputMethod {
void unbindInput();
void startInput(in IBinder startInputToken, in IRemoteInputConnection inputConnection,
in EditorInfo editorInfo, boolean restarting, int navigationBarFlags,
in ImeOnBackInvokedDispatcher imeDispatcher);
parcelable StartInputParams {
IBinder startInputToken;
IRemoteInputConnection remoteInputConnection;
EditorInfo editorInfo;
boolean restarting;
int navigationBarFlags;
ImeOnBackInvokedDispatcher imeDispatcher;
}
void startInput(in StartInputParams params);
void onNavButtonFlagsChanged(int navButtonFlags);

View File

@@ -148,13 +148,19 @@ final class IInputMethodInvoker {
}
@AnyThread
void startInput(IBinder startInputToken, IRemoteInputConnection inputConnection,
void startInput(IBinder startInputToken, IRemoteInputConnection remoteInputConnection,
EditorInfo editorInfo, boolean restarting,
@InputMethodNavButtonFlags int navButtonFlags,
@NonNull ImeOnBackInvokedDispatcher imeDispatcher) {
final IInputMethod.StartInputParams params = new IInputMethod.StartInputParams();
params.startInputToken = startInputToken;
params.remoteInputConnection = remoteInputConnection;
params.editorInfo = editorInfo;
params.restarting = restarting;
params.navigationBarFlags = navButtonFlags;
params.imeDispatcher = imeDispatcher;
try {
mTarget.startInput(startInputToken, inputConnection, editorInfo, restarting,
navButtonFlags, imeDispatcher);
mTarget.startInput(params);
} catch (RemoteException e) {
logRemoteException(e);
}