Merge ControlledInputConnectionWrapper into parent class

Since ControlledInputConnectionWrapper is the only derived class
of IInputConnectionWrapper hence it doesn't have a reason keep them
separate.

Bug: 167948374
Bug: 163450598
Test: atest CtsInputMethodTestCases
Change-Id: Ice1ea23dcb2351b56ef03b507d8aec8f8fb7b30a
This commit is contained in:
Ming-Shin Lu
2021-03-05 01:41:02 +08:00
parent f4f6a9ebef
commit af47729a15
2 changed files with 89 additions and 99 deletions

View File

@@ -106,7 +106,6 @@ import com.android.internal.view.InputBindResult;
import java.io.FileDescriptor;
import java.io.PrintWriter;
import java.lang.ref.WeakReference;
import java.lang.reflect.Proxy;
import java.util.Arrays;
import java.util.Collections;
@@ -413,7 +412,7 @@ public final class InputMethodManager {
* The InputConnection that was last retrieved from the served view.
*/
@UnsupportedAppUsage(maxTargetSdk = Build.VERSION_CODES.P, trackingBug = 115609023)
ControlledInputConnectionWrapper mServedInputConnectionWrapper;
IInputConnectionWrapper mServedInputConnectionWrapper;
/**
* The completions that were last provided by the served view.
*/
@@ -740,8 +739,7 @@ public final class InputMethodManager {
/**
* Checks whether the active input connection (if any) is for the given view.
*
* TODO(b/160968797): Remove this method and move mServedInputConnectionWrapper to
* ImeFocusController.
* TODO(b/182259171): Clean-up hasActiveConnection to simplify the logic.
*
* Note that this method is only intended for restarting input after focus gain
* (e.g. b/160391516), DO NOT leverage this method to do another check.
@@ -755,7 +753,7 @@ public final class InputMethodManager {
return mServedInputConnectionWrapper != null
&& mServedInputConnectionWrapper.isActive()
&& mServedInputConnectionWrapper.mServedView.get() == view;
&& mServedInputConnectionWrapper.getServedView() == view;
}
}
}
@@ -1022,77 +1020,6 @@ public final class InputMethodManager {
}
}
private static class ControlledInputConnectionWrapper extends IInputConnectionWrapper {
private final InputMethodManager mParentInputMethodManager;
private final WeakReference<View> mServedView;
ControlledInputConnectionWrapper(Looper icLooper, InputConnection conn,
InputMethodManager inputMethodManager, View servedView) {
super(icLooper, conn);
mParentInputMethodManager = inputMethodManager;
mServedView = new WeakReference<>(servedView);
}
@Override
public boolean isActive() {
return mParentInputMethodManager.mActive && !isFinished();
}
@Override
public InputMethodManager getIMM() {
return mParentInputMethodManager;
}
void deactivate() {
if (isFinished()) {
// This is a small performance optimization. Still only the 1st call of
// reportFinish() will take effect.
return;
}
closeConnection();
// Notify the app that the InputConnection was closed.
final View servedView = mServedView.get();
if (servedView != null) {
final Handler handler = servedView.getHandler();
// The handler is null if the view is already detached. When that's the case, for
// now, we simply don't dispatch this callback.
if (handler != null) {
if (DEBUG) {
Log.v(TAG, "Calling View.onInputConnectionClosed: view=" + servedView);
}
if (handler.getLooper().isCurrentThread()) {
servedView.onInputConnectionClosedInternal();
} else {
handler.post(servedView::onInputConnectionClosedInternal);
}
}
}
}
@Override
public String toString() {
return "ControlledInputConnectionWrapper{"
+ "connection=" + getInputConnection()
+ " finished=" + isFinished()
+ " mParentInputMethodManager.mActive=" + mParentInputMethodManager.mActive
+ " mServedView=" + mServedView.get()
+ "}";
}
void dumpDebug(ProtoOutputStream proto, long fieldId) {
// Check that the call is initiated in the main thread of the current InputConnection
// {@link InputConnection#getHandler} since the messages to IInputConnectionWrapper are
// executed on this thread. Otherwise the messages are dispatched to the correct thread
// in IInputConnectionWrapper, but this is not wanted while dumpng, for performance
// reasons.
if (getInputConnection() instanceof DumpableInputConnection && Looper.myLooper()
== getLooper()) {
((DumpableInputConnection) getInputConnection()).dumpDebug(proto, fieldId);
}
}
}
final IInputMethodClient.Stub mClient = new IInputMethodClient.Stub() {
@Override
protected void dump(FileDescriptor fd, PrintWriter fout, String[] args) {
@@ -1256,8 +1183,7 @@ public final class InputMethodManager {
mMainLooper = looper;
mH = new H(looper);
mDisplayId = displayId;
mIInputContext = new ControlledInputConnectionWrapper(looper, mDummyInputConnection, this,
null);
mIInputContext = new IInputConnectionWrapper(looper, mDummyInputConnection, this, null);
}
/**
@@ -2063,7 +1989,7 @@ public final class InputMethodManager {
mServedInputConnectionWrapper.deactivate();
mServedInputConnectionWrapper = null;
}
ControlledInputConnectionWrapper servedContext;
IInputConnectionWrapper servedContext;
final int missingMethodFlags;
if (ic != null) {
mCursorSelStart = tba.initialSelStart;
@@ -2080,7 +2006,7 @@ public final class InputMethodManager {
} else {
icHandler = ic.getHandler();
}
servedContext = new ControlledInputConnectionWrapper(
servedContext = new IInputConnectionWrapper(
icHandler != null ? icHandler.getLooper() : vh.getLooper(), ic, this, view);
} else {
servedContext = null;

View File

@@ -31,8 +31,10 @@ import android.util.imetracing.ImeTracing;
import android.util.imetracing.InputConnectionHelper;
import android.util.proto.ProtoOutputStream;
import android.view.KeyEvent;
import android.view.View;
import android.view.inputmethod.CompletionInfo;
import android.view.inputmethod.CorrectionInfo;
import android.view.inputmethod.DumpableInputConnection;
import android.view.inputmethod.ExtractedText;
import android.view.inputmethod.ExtractedTextRequest;
import android.view.inputmethod.InputConnection;
@@ -49,7 +51,9 @@ import com.android.internal.inputmethod.IIntResultCallback;
import com.android.internal.inputmethod.ISurroundingTextResultCallback;
import com.android.internal.os.SomeArgs;
public abstract class IInputConnectionWrapper extends IInputContext.Stub {
import java.lang.ref.WeakReference;
public final class IInputConnectionWrapper extends IInputContext.Stub {
private static final String TAG = "IInputConnectionWrapper";
private static final boolean DEBUG = false;
@@ -90,10 +94,13 @@ public abstract class IInputConnectionWrapper extends IInputContext.Stub {
private Looper mMainLooper;
private Handler mH;
@UnsupportedAppUsage(maxTargetSdk = Build.VERSION_CODES.R, trackingBug = 170729553)
private Object mLock = new Object();
private final Object mLock = new Object();
@GuardedBy("mLock")
private boolean mFinished = false;
private final InputMethodManager mParentInputMethodManager;
private final WeakReference<View> mServedView;
class MyHandler extends Handler {
MyHandler(Looper looper) {
super(looper);
@@ -104,11 +111,15 @@ public abstract class IInputConnectionWrapper extends IInputContext.Stub {
executeMessage(msg);
}
}
public IInputConnectionWrapper(Looper mainLooper, @NonNull InputConnection inputConnection) {
public IInputConnectionWrapper(@NonNull Looper mainLooper,
@NonNull InputConnection inputConnection,
@NonNull InputMethodManager inputMethodManager, @Nullable View servedView) {
mInputConnection = inputConnection;
mMainLooper = mainLooper;
mH = new MyHandler(mMainLooper);
mParentInputMethodManager = inputMethodManager;
mServedView = new WeakReference<>(servedView);
}
@Nullable
@@ -118,21 +129,70 @@ public abstract class IInputConnectionWrapper extends IInputContext.Stub {
}
}
protected Looper getLooper() {
synchronized (mMainLooper) {
return mMainLooper;
}
}
protected boolean isFinished() {
private boolean isFinished() {
synchronized (mLock) {
return mFinished;
}
}
protected abstract boolean isActive();
public boolean isActive() {
return mParentInputMethodManager.isActive() && !isFinished();
}
protected abstract InputMethodManager getIMM();
public View getServedView() {
return mServedView.get();
}
public void deactivate() {
if (isFinished()) {
// This is a small performance optimization. Still only the 1st call of
// reportFinish() will take effect.
return;
}
closeConnection();
// Notify the app that the InputConnection was closed.
final View servedView = mServedView.get();
if (servedView != null) {
final Handler handler = servedView.getHandler();
// The handler is null if the view is already detached. When that's the case, for
// now, we simply don't dispatch this callback.
if (handler != null) {
if (DEBUG) {
Log.v(TAG, "Calling View.onInputConnectionClosed: view=" + servedView);
}
if (handler.getLooper().isCurrentThread()) {
servedView.onInputConnectionClosedInternal();
} else {
handler.post(servedView::onInputConnectionClosedInternal);
}
}
}
}
@Override
public String toString() {
return "IInputConnectionWrapper{"
+ "connection=" + getInputConnection()
+ " finished=" + isFinished()
+ " mParentInputMethodManager.isActive()=" + mParentInputMethodManager.isActive()
+ " mServedView=" + mServedView.get()
+ "}";
}
public void dumpDebug(ProtoOutputStream proto, long fieldId) {
synchronized (mLock) {
// Check that the call is initiated in the main thread of the current InputConnection
// {@link InputConnection#getHandler} since the messages to IInputConnectionWrapper are
// executed on this thread. Otherwise the messages are dispatched to the correct thread
// in IInputConnectionWrapper, but this is not wanted while dumpng, for performance
// reasons.
if ((mInputConnection instanceof DumpableInputConnection)
&& Looper.myLooper() == mMainLooper) {
((DumpableInputConnection) mInputConnection).dumpDebug(proto, fieldId);
}
}
}
public void getTextAfterCursor(int length, int flags, ICharSequenceResultCallback callback) {
dispatchMessage(mH.obtainMessage(DO_GET_TEXT_AFTER_CURSOR, length, flags, callback));
@@ -161,6 +221,10 @@ public abstract class IInputConnectionWrapper extends IInputContext.Stub {
dispatchMessage(mH.obtainMessage(DO_GET_SURROUNDING_TEXT, flags, 0 /* unused */, args));
}
public void setImeTemporarilyConsumesInput(boolean imeTemporarilyConsumesInput) {
// no-op
}
public void getCursorCapsMode(int reqModes, IIntResultCallback callback) {
dispatchMessage(
mH.obtainMessage(DO_GET_CURSOR_CAPS_MODE, reqModes, 0 /* unused */, callback));
@@ -309,7 +373,7 @@ public abstract class IInputConnectionWrapper extends IInputContext.Stub {
icProto = InputConnectionHelper.buildGetTextAfterCursorProto(msg.arg1,
msg.arg2, result);
ImeTracing.getInstance().triggerClientDump(
TAG + "#getTextAfterCursor", getIMM(), icProto);
TAG + "#getTextAfterCursor", mParentInputMethodManager, icProto);
}
try {
callback.onResult(result);
@@ -339,7 +403,7 @@ public abstract class IInputConnectionWrapper extends IInputContext.Stub {
icProto = InputConnectionHelper.buildGetTextBeforeCursorProto(msg.arg1,
msg.arg2, result);
ImeTracing.getInstance().triggerClientDump(
TAG + "#getTextBeforeCursor", getIMM(), icProto);
TAG + "#getTextBeforeCursor", mParentInputMethodManager, icProto);
}
try {
callback.onResult(result);
@@ -368,7 +432,7 @@ public abstract class IInputConnectionWrapper extends IInputContext.Stub {
if (ImeTracing.getInstance().isEnabled()) {
icProto = InputConnectionHelper.buildGetSelectedTextProto(msg.arg1, result);
ImeTracing.getInstance().triggerClientDump(
TAG + "#getSelectedText", getIMM(), icProto);
TAG + "#getSelectedText", mParentInputMethodManager, icProto);
}
try {
callback.onResult(result);
@@ -402,7 +466,7 @@ public abstract class IInputConnectionWrapper extends IInputContext.Stub {
icProto = InputConnectionHelper.buildGetSurroundingTextProto(beforeLength,
afterLength, flags, result);
ImeTracing.getInstance().triggerClientDump(
TAG + "#getSurroundingText", getIMM(), icProto);
TAG + "#getSurroundingText", mParentInputMethodManager, icProto);
}
try {
callback.onResult(result);
@@ -432,7 +496,7 @@ public abstract class IInputConnectionWrapper extends IInputContext.Stub {
icProto = InputConnectionHelper.buildGetCursorCapsModeProto(msg.arg1,
result);
ImeTracing.getInstance().triggerClientDump(
TAG + "#getCursorCapsMode", getIMM(), icProto);
TAG + "#getCursorCapsMode", mParentInputMethodManager, icProto);
}
try {
callback.onResult(result);
@@ -464,7 +528,7 @@ public abstract class IInputConnectionWrapper extends IInputContext.Stub {
icProto = InputConnectionHelper.buildGetExtractedTextProto(request,
msg.arg1, result);
ImeTracing.getInstance().triggerClientDump(
TAG + "#getExtractedText", getIMM(), icProto);
TAG + "#getExtractedText", mParentInputMethodManager, icProto);
}
try {
callback.onResult(result);