in com/android/internal/view/IInputConnectionWrapper.java [233:582]
void executeMessage(Message msg) {
switch (msg.what) {
case DO_GET_TEXT_AFTER_CURSOR: {
SomeArgs args = (SomeArgs)msg.obj;
try {
final IInputContextCallback callback = (IInputContextCallback) args.arg6;
final int callbackSeq = args.argi6;
InputConnection ic = getInputConnection();
if (ic == null || !isActive()) {
Log.w(TAG, "getTextAfterCursor on inactive InputConnection");
callback.setTextAfterCursor(null, callbackSeq);
return;
}
callback.setTextAfterCursor(ic.getTextAfterCursor(
msg.arg1, msg.arg2), callbackSeq);
} catch (RemoteException e) {
Log.w(TAG, "Got RemoteException calling setTextAfterCursor", e);
} finally {
args.recycle();
}
return;
}
case DO_GET_TEXT_BEFORE_CURSOR: {
SomeArgs args = (SomeArgs)msg.obj;
try {
final IInputContextCallback callback = (IInputContextCallback) args.arg6;
final int callbackSeq = args.argi6;
InputConnection ic = getInputConnection();
if (ic == null || !isActive()) {
Log.w(TAG, "getTextBeforeCursor on inactive InputConnection");
callback.setTextBeforeCursor(null, callbackSeq);
return;
}
callback.setTextBeforeCursor(ic.getTextBeforeCursor(
msg.arg1, msg.arg2), callbackSeq);
} catch (RemoteException e) {
Log.w(TAG, "Got RemoteException calling setTextBeforeCursor", e);
} finally {
args.recycle();
}
return;
}
case DO_GET_SELECTED_TEXT: {
SomeArgs args = (SomeArgs)msg.obj;
try {
final IInputContextCallback callback = (IInputContextCallback) args.arg6;
final int callbackSeq = args.argi6;
InputConnection ic = getInputConnection();
if (ic == null || !isActive()) {
Log.w(TAG, "getSelectedText on inactive InputConnection");
callback.setSelectedText(null, callbackSeq);
return;
}
callback.setSelectedText(ic.getSelectedText(
msg.arg1), callbackSeq);
} catch (RemoteException e) {
Log.w(TAG, "Got RemoteException calling setSelectedText", e);
} finally {
args.recycle();
}
return;
}
case DO_GET_CURSOR_CAPS_MODE: {
SomeArgs args = (SomeArgs)msg.obj;
try {
final IInputContextCallback callback = (IInputContextCallback) args.arg6;
final int callbackSeq = args.argi6;
InputConnection ic = getInputConnection();
if (ic == null || !isActive()) {
Log.w(TAG, "getCursorCapsMode on inactive InputConnection");
callback.setCursorCapsMode(0, callbackSeq);
return;
}
callback.setCursorCapsMode(ic.getCursorCapsMode(msg.arg1),
callbackSeq);
} catch (RemoteException e) {
Log.w(TAG, "Got RemoteException calling setCursorCapsMode", e);
} finally {
args.recycle();
}
return;
}
case DO_GET_EXTRACTED_TEXT: {
SomeArgs args = (SomeArgs)msg.obj;
try {
final IInputContextCallback callback = (IInputContextCallback) args.arg6;
final int callbackSeq = args.argi6;
InputConnection ic = getInputConnection();
if (ic == null || !isActive()) {
Log.w(TAG, "getExtractedText on inactive InputConnection");
callback.setExtractedText(null, callbackSeq);
return;
}
callback.setExtractedText(ic.getExtractedText(
(ExtractedTextRequest)args.arg1, msg.arg1), callbackSeq);
} catch (RemoteException e) {
Log.w(TAG, "Got RemoteException calling setExtractedText", e);
} finally {
args.recycle();
}
return;
}
case DO_COMMIT_TEXT: {
InputConnection ic = getInputConnection();
if (ic == null || !isActive()) {
Log.w(TAG, "commitText on inactive InputConnection");
return;
}
ic.commitText((CharSequence)msg.obj, msg.arg1);
onUserAction();
return;
}
case DO_SET_SELECTION: {
InputConnection ic = getInputConnection();
if (ic == null || !isActive()) {
Log.w(TAG, "setSelection on inactive InputConnection");
return;
}
ic.setSelection(msg.arg1, msg.arg2);
return;
}
case DO_PERFORM_EDITOR_ACTION: {
InputConnection ic = getInputConnection();
if (ic == null || !isActive()) {
Log.w(TAG, "performEditorAction on inactive InputConnection");
return;
}
ic.performEditorAction(msg.arg1);
return;
}
case DO_PERFORM_CONTEXT_MENU_ACTION: {
InputConnection ic = getInputConnection();
if (ic == null || !isActive()) {
Log.w(TAG, "performContextMenuAction on inactive InputConnection");
return;
}
ic.performContextMenuAction(msg.arg1);
return;
}
case DO_COMMIT_COMPLETION: {
InputConnection ic = getInputConnection();
if (ic == null || !isActive()) {
Log.w(TAG, "commitCompletion on inactive InputConnection");
return;
}
ic.commitCompletion((CompletionInfo)msg.obj);
return;
}
case DO_COMMIT_CORRECTION: {
InputConnection ic = getInputConnection();
if (ic == null || !isActive()) {
Log.w(TAG, "commitCorrection on inactive InputConnection");
return;
}
ic.commitCorrection((CorrectionInfo)msg.obj);
return;
}
case DO_SET_COMPOSING_TEXT: {
InputConnection ic = getInputConnection();
if (ic == null || !isActive()) {
Log.w(TAG, "setComposingText on inactive InputConnection");
return;
}
ic.setComposingText((CharSequence)msg.obj, msg.arg1);
onUserAction();
return;
}
case DO_SET_COMPOSING_REGION: {
InputConnection ic = getInputConnection();
if (ic == null || !isActive()) {
Log.w(TAG, "setComposingRegion on inactive InputConnection");
return;
}
ic.setComposingRegion(msg.arg1, msg.arg2);
return;
}
case DO_FINISH_COMPOSING_TEXT: {
if (isFinished()) {
// In this case, #finishComposingText() is guaranteed to be called already.
// There should be no negative impact if we ignore this call silently.
if (DEBUG) {
Log.w(TAG, "Bug 35301295: Redundant finishComposingText.");
}
return;
}
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) {
Log.w(TAG, "finishComposingText on inactive InputConnection");
return;
}
ic.finishComposingText();
return;
}
case DO_SEND_KEY_EVENT: {
InputConnection ic = getInputConnection();
if (ic == null || !isActive()) {
Log.w(TAG, "sendKeyEvent on inactive InputConnection");
return;
}
ic.sendKeyEvent((KeyEvent)msg.obj);
onUserAction();
return;
}
case DO_CLEAR_META_KEY_STATES: {
InputConnection ic = getInputConnection();
if (ic == null || !isActive()) {
Log.w(TAG, "clearMetaKeyStates on inactive InputConnection");
return;
}
ic.clearMetaKeyStates(msg.arg1);
return;
}
case DO_DELETE_SURROUNDING_TEXT: {
InputConnection ic = getInputConnection();
if (ic == null || !isActive()) {
Log.w(TAG, "deleteSurroundingText on inactive InputConnection");
return;
}
ic.deleteSurroundingText(msg.arg1, msg.arg2);
return;
}
case DO_DELETE_SURROUNDING_TEXT_IN_CODE_POINTS: {
InputConnection ic = getInputConnection();
if (ic == null || !isActive()) {
Log.w(TAG, "deleteSurroundingTextInCodePoints on inactive InputConnection");
return;
}
ic.deleteSurroundingTextInCodePoints(msg.arg1, msg.arg2);
return;
}
case DO_BEGIN_BATCH_EDIT: {
InputConnection ic = getInputConnection();
if (ic == null || !isActive()) {
Log.w(TAG, "beginBatchEdit on inactive InputConnection");
return;
}
ic.beginBatchEdit();
return;
}
case DO_END_BATCH_EDIT: {
InputConnection ic = getInputConnection();
if (ic == null || !isActive()) {
Log.w(TAG, "endBatchEdit on inactive InputConnection");
return;
}
ic.endBatchEdit();
return;
}
case DO_PERFORM_PRIVATE_COMMAND: {
final SomeArgs args = (SomeArgs) msg.obj;
try {
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");
return;
}
ic.performPrivateCommand(action, data);
} finally {
args.recycle();
}
return;
}
case DO_REQUEST_UPDATE_CURSOR_ANCHOR_INFO: {
SomeArgs args = (SomeArgs)msg.obj;
try {
final IInputContextCallback callback = (IInputContextCallback) args.arg6;
final int callbackSeq = args.argi6;
InputConnection ic = getInputConnection();
if (ic == null || !isActive()) {
Log.w(TAG, "requestCursorAnchorInfo on inactive InputConnection");
callback.setRequestUpdateCursorAnchorInfoResult(false, callbackSeq);
return;
}
callback.setRequestUpdateCursorAnchorInfoResult(
ic.requestCursorUpdates(msg.arg1), callbackSeq);
} catch (RemoteException e) {
Log.w(TAG, "Got RemoteException calling requestCursorAnchorInfo", e);
} finally {
args.recycle();
}
return;
}
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;
}
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;
}
}
return;
}
case DO_COMMIT_CONTENT: {
final int flags = msg.arg1;
SomeArgs args = (SomeArgs) msg.obj;
try {
final IInputContextCallback callback = (IInputContextCallback) args.arg6;
final int callbackSeq = args.argi6;
InputConnection ic = getInputConnection();
if (ic == null || !isActive()) {
Log.w(TAG, "commitContent on inactive InputConnection");
callback.setCommitContentResult(false, callbackSeq);
return;
}
final InputContentInfo inputContentInfo = (InputContentInfo) args.arg1;
if (inputContentInfo == null || !inputContentInfo.validate()) {
Log.w(TAG, "commitContent with invalid inputContentInfo="
+ inputContentInfo);
callback.setCommitContentResult(false, callbackSeq);
return;
}
final boolean result =
ic.commitContent(inputContentInfo, flags, (Bundle) args.arg2);
callback.setCommitContentResult(result, callbackSeq);
} catch (RemoteException e) {
Log.w(TAG, "Got RemoteException calling commitContent", e);
} finally {
args.recycle();
}
return;
}
}
Log.w(TAG, "Unhandled message code: " + msg.what);
}