Loading core/java/android/view/inputmethod/InputMethodManager.java +6 −80 Original line number Diff line number Diff line Loading @@ -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; Loading Loading @@ -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. */ Loading Loading @@ -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. Loading @@ -755,7 +753,7 @@ public final class InputMethodManager { return mServedInputConnectionWrapper != null && mServedInputConnectionWrapper.isActive() && mServedInputConnectionWrapper.mServedView.get() == view; && mServedInputConnectionWrapper.getServedView() == view; } } } Loading Loading @@ -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) { Loading Loading @@ -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); } /** Loading Loading @@ -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; Loading @@ -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; Loading core/java/com/android/internal/view/IInputConnectionWrapper.java +82 −18 Original line number Diff line number Diff line Loading @@ -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; Loading @@ -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; Loading Loading @@ -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); Loading @@ -105,10 +112,14 @@ public abstract class IInputConnectionWrapper extends IInputContext.Stub { } } 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 Loading @@ -118,21 +129,70 @@ public abstract class IInputConnectionWrapper extends IInputContext.Stub { } } protected Looper getLooper() { synchronized (mMainLooper) { return mMainLooper; private boolean isFinished() { synchronized (mLock) { return mFinished; } } protected boolean isFinished() { synchronized (mLock) { return mFinished; public boolean isActive() { return mParentInputMethodManager.isActive() && !isFinished(); } public View getServedView() { return mServedView.get(); } protected abstract boolean isActive(); public void deactivate() { if (isFinished()) { // This is a small performance optimization. Still only the 1st call of // reportFinish() will take effect. return; } closeConnection(); protected abstract InputMethodManager getIMM(); // 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)); Loading Loading @@ -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)); Loading Loading @@ -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); Loading Loading @@ -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); Loading Loading @@ -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); Loading Loading @@ -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); Loading Loading @@ -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); Loading Loading @@ -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); Loading Loading
core/java/android/view/inputmethod/InputMethodManager.java +6 −80 Original line number Diff line number Diff line Loading @@ -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; Loading Loading @@ -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. */ Loading Loading @@ -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. Loading @@ -755,7 +753,7 @@ public final class InputMethodManager { return mServedInputConnectionWrapper != null && mServedInputConnectionWrapper.isActive() && mServedInputConnectionWrapper.mServedView.get() == view; && mServedInputConnectionWrapper.getServedView() == view; } } } Loading Loading @@ -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) { Loading Loading @@ -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); } /** Loading Loading @@ -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; Loading @@ -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; Loading
core/java/com/android/internal/view/IInputConnectionWrapper.java +82 −18 Original line number Diff line number Diff line Loading @@ -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; Loading @@ -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; Loading Loading @@ -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); Loading @@ -105,10 +112,14 @@ public abstract class IInputConnectionWrapper extends IInputContext.Stub { } } 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 Loading @@ -118,21 +129,70 @@ public abstract class IInputConnectionWrapper extends IInputContext.Stub { } } protected Looper getLooper() { synchronized (mMainLooper) { return mMainLooper; private boolean isFinished() { synchronized (mLock) { return mFinished; } } protected boolean isFinished() { synchronized (mLock) { return mFinished; public boolean isActive() { return mParentInputMethodManager.isActive() && !isFinished(); } public View getServedView() { return mServedView.get(); } protected abstract boolean isActive(); public void deactivate() { if (isFinished()) { // This is a small performance optimization. Still only the 1st call of // reportFinish() will take effect. return; } closeConnection(); protected abstract InputMethodManager getIMM(); // 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)); Loading Loading @@ -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)); Loading Loading @@ -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); Loading Loading @@ -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); Loading Loading @@ -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); Loading Loading @@ -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); Loading Loading @@ -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); Loading Loading @@ -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); Loading