Fix InputMethodServiceInternal lifetime

This is a follow up CL to my recent CL [1], which aimed to consolidate
dependencies on InputMethodService from RemoteInputConnection.

One thing I overlooked was that InputMethodService did not retain a
strong reference to InputMethodServiceInternal object that I
introduced there, which means that the newly instantiated
InputMethodServiceInternal could be garbage-collected even before
InputMethodService became unreachable.

As a result, the following InputConnection APIs could start failing at
some point and would never work without restarting the IME, which is
likely to be the root cause of the recent flakiness in
InputConnectionEndToEndTest discussed in Bug 193822485.

  * InputConnection#requestCursorUpdates()
  * InputConnection#commitContent()

Also, the following functionality might have stopped working at some
point.

  * InputMethodService#dump()
  * InputConnection tracing in IME tracing
  * Updating IME switching order based on user inputs

With this CL, the InputMethodServiceInternal instance is guaranteed to
be instantiated once and remain to be alive until
AbstractInputMethodService becomes unreachable.

 [1]: I2aeeeacd27195ce10059d6590e098a4a969e774d
      a975bfc447

Fix: 193822485
Fix: 199288389
Test: atest CtsInputMethodTestCases
Test: Manually verified with Imege Keyboard sample IME/app
Change-Id: I7ee0270bad94ed606048bfaf76e8545336715d83
This commit is contained in:
Yohei Yukawa
2021-09-30 13:13:56 -07:00
parent dc0ffe41dd
commit 1ab4cb2da6

View File

@@ -66,7 +66,17 @@ import java.io.PrintWriter;
public abstract class AbstractInputMethodService extends WindowProviderService
implements KeyEvent.Callback {
private InputMethod mInputMethod;
/**
* Keep the strong reference to {@link InputMethodServiceInternal} to ensure that it will not be
* garbage-collected until {@link AbstractInputMethodService} gets garbage-collected.
*
* <p>This is necessary because {@link RemoteInputConnection} internally uses
* {@link java.lang.ref.WeakReference} to hold {@link InputMethodServiceInternal}.</p>
*/
@Nullable
private InputMethodServiceInternal mInputMethodServiceInternal;
final KeyEvent.DispatcherState mDispatcherState
= new KeyEvent.DispatcherState();
@@ -225,7 +235,10 @@ public abstract class AbstractInputMethodService extends WindowProviderService
if (mInputMethod == null) {
mInputMethod = onCreateInputMethodInterface();
}
return new IInputMethodWrapper(createInputMethodServiceInternal(), mInputMethod);
if (mInputMethodServiceInternal == null) {
mInputMethodServiceInternal = createInputMethodServiceInternal();
}
return new IInputMethodWrapper(mInputMethodServiceInternal, mInputMethod);
}
/**