Android原生输入法输入数字流程
//按下数字1,com.android.inputmethod.latin
NativePostImeInputStage::onProcess
ViewPostImeInputStage::onProcess
@frameworks/base/core/java/android/app/Dialog.java
dispatchTouchEvent //MotionEvent { action=ACTION_DOWN, actionButton=0, id[0]=0, x[0]=193.0, y[0]=690.0, toolType[0]=TOOL_TYPE_FINGER, displayId=0
@frameworks/base/core/java/com/android/internal/policy/PhoneWindow.java
mWindow.superDispatchTouchEvent(ev)
@frameworks/base/core/java/com/android/internal/policy/DecorView.java
mDecor.superDispatchTouchEvent(event);
@frameworks/base/core/java/android/view/View.java
super.dispatchTouchEvent(event);
@packages/inputmethods/LatinIME/java/src/com/android/inputmethod/keyboard/MainKeyboardView.java
if (!result && onTouchEvent(event)) {
@packages/inputmethods/LatinIME/java/src/com/android/inputmethod/keyboard/PointerTracker.java
tracker.processMotionEvent(event, mKeyDetector);
case MotionEvent.ACTION_DOWN:
case MotionEvent.ACTION_POINTER_DOWN:
onDownEvent(x, y, eventTime, keyDetector);
final Key key = getKeyOn(x, y);
@packages/inputmethods/LatinIME/java/src/com/android/inputmethod/keyboard/KeyDetector.java
return mKeyDetector.detectHitKey(x, y);
for (final Key key: mKeyboard.getNearestKeys(touchX, touchY)) {
@packages/inputmethods/LatinIME/java/src/com/android/inputmethod/keyboard/Key.java
final int distance = key.squaredDistanceToEdge(touchX, touchY);
if (primaryKey == null || distance < minDistance || key.getCode() > primaryKey.getCode()) {
minDistance = distance;
primaryKey = key; //private final int mCode; //ASCII码, key=1 20,12 345x90 !icon/undefined/normal
onDownEventInternal(x, y, eventTime);
Key key = onDownKey(x, y, eventTime);
onMoveToNewKey(onMoveKeyInternal(x, y), x, y);
mKeyDetector.detectHitKey(x, y);
//抬起,com.android.inputmethod.latin
NativePostImeInputStage::onProcess
ViewPostImeInputStage::onProcess
@frameworks/base/core/java/android/app/Dialog.java
dispatchTouchEvent //MotionEvent { action=ACTION_DOWN, actionButton=0, id[0]=0, x[0]=193.0, y[0]=690.0, toolType[0]=TOOL_TYPE_FINGER, displayId=0
@frameworks/base/core/java/com/android/internal/policy/PhoneWindow.java
mWindow.superDispatchTouchEvent(ev)
@frameworks/base/core/java/com/android/internal/policy/DecorView.java
mDecor.superDispatchTouchEvent(event);
@frameworks/base/core/java/android/view/View.java
super.dispatchTouchEvent(event);
@packages/inputmethods/LatinIME/java/src/com/android/inputmethod/keyboard/MainKeyboardView.java
if (!result && onTouchEvent(event)) {
@packages/inputmethods/LatinIME/java/src/com/android/inputmethod/keyboard/PointerTracker.java
tracker.processMotionEvent(event, mKeyDetector);
case MotionEvent.ACTION_UP:
case MotionEvent.ACTION_POINTER_UP:
onUpEvent(x, y, eventTime);
onUpEventInternal(x, y, eventTime);
detectAndSendKey(currentKey, mKeyX, mKeyY, eventTime);
callListenerOnCodeInput(key, code, x, y, eventTime, false /* isKeyRepeat */);
if (key.isEnabled() || altersCode) {
@packages/inputmethods/LatinIME/java/src/com/android/inputmethod/keyboard/internal/TypingTimeRecorder.java
sTypingTimeRecorder.onCodeInput(code, eventTime);
else if (code != Constants.CODE_UNSPECIFIED) {
@packages/inputmethods/LatinIME/java/src/com/android/inputmethod/latin/LatinIME.java
} else { sListener.onCodeInput(code, Constants.NOT_A_COORDINATE, Constants.NOT_A_COORDINATE, isKeyRepeat);
final Event event = createSoftwareKeypressEvent(getCodePointForKeyboard(codePoint), keyX, keyY, isKeyRepeat);
onEvent(event);
@packages/inputmethods/LatinIME/java/src/com/android/inputmethod/latin/inputlogic/InputLogic.java
final InputTransaction completeInputTransaction = mInputLogic.onCodeInput(mSettings.getCurrent(), event, mKeyboardSwitcher.getKeyboardShiftMode(), mKeyboardSwitcher.getCurrentKeyboardScriptId(), mHandler);
handleNonFunctionalEvent(currentEvent, inputTransaction, handler);
default: handleNonSpecialCharacterEvent(event, inputTransaction, handler);
handleNonSeparatorEvent(event, inputTransaction.mSettingsValues, inputTransaction);
final boolean swapWeakSpace = tryStripSpaceAndReturnWhetherShouldSwapInstead(event, inputTransaction);
sendKeyCodePoint(settingsValues, codePoint);
if (codePoint >= '0' && codePoint <= '9') { sendDownUpKeyEvent(codePoint - '0' + KeyEvent.KEYCODE_0); }
@packages/inputmethods/LatinIME/java/src/com/android/inputmethod/latin/RichInputConnection.java
mConnection.sendKeyEvent(new KeyEvent(eventTime, eventTime, KeyEvent.ACTION_DOWN, keyCode, 0, 0, KeyCharacterMap.VIRTUAL_KEYBOARD, 0, KeyEvent.FLAG_SOFT_KEYBOARD | KeyEvent.FLAG_KEEP_TOUCH_MODE));
if (keyEvent.getAction() == KeyEvent.ACTION_DOWN) {
final String text = StringUtils.newSingleCodePointString(keyEvent.getUnicodeChar());
mCommittedTextBeforeComposingText.append(text);
@frameworks/base/core/java/com/android/internal/view/InputConnectionWrapper.java
if (isConnected()) { mIC.sendKeyEvent(keyEvent); }
mIInputContext.sendKeyEvent(event); //跨进程通信,输入法应用调用app应用的sendKeyEvent, 这里的app是com.example.myapplication
dispatchMessage(obtainMessageO(DO_SEND_KEY_EVENT, event));
case DO_SEND_KEY_EVENT: {
InputConnection ic = getInputConnection();
@frameworks/base/core/java/android/view/inputmethod/InputConnectionWrapper.java
ic.sendKeyEvent((KeyEvent) msg.obj);
@frameworks/base/core/java/android/view/inputmethod/BaseInputConnection.java
mTarget.sendKeyEvent(event);
@frameworks/base/core/java/android/view/inputmethod/InputMethodManager.java
mIMM.dispatchKeyEventFromInputMethod(mTargetView, event);
final InputMethodManager fallbackImm = getFallbackInputMethodManagerIfNecessary(targetView);
if (fallbackImm != null) { return fallbackImm.dispatchKeyEventFromInputMethod(targetView, event);}
ViewRootImpl viewRootImpl = targetView != null ? targetView.getViewRootImpl() : null;
@frameworks/base/core/java/android/view/ViewRootImpl.java
if (viewRootImpl != null) { viewRootImpl.dispatchKeyFromIme(event); }
Message msg = mHandler.obtainMessage(MSG_DISPATCH_KEY_FROM_IME, event);
mHandler.sendMessage(msg);
case MSG_DISPATCH_KEY_FROM_IME: { enqueueInputEvent(event, null, QueuedInputEvent.FLAG_DELIVER_POST_IME, true); } //from IME to DecorView@9d665bb[MainActivity]
QueuedInputEvent q = obtainQueuedInputEvent(event, receiver, flags);
doProcessInputEvents();
deliverInputEvent(q);
stage = q.shouldSkipIme() ? mFirstPostImeInputStage : mFirstInputStage;
stage.deliver(q);
EarlyPostImeInputStage::onProcess
stage.deliver(q);
NativePostImeInputStage::onProcess
stage.deliver(q); //QueuedInputEvent{flags=DELIVER_POST_IME|FINISHED|FINISHED_HANDLED, hasNextQueuedEvent=true, hasInputEventReceiver=false, mEvent=KeyEvent { action=ACTION_DOWN, keyCode=KEYCODE_1, scanCode=0, metaState=0, flags=0x6, repeatCount=0, eventTime=37602, downTime=37602, deviceId=-1, source=0x0, displayId=0 }}
ViewPostImeInputStage::onProcess
return processKeyEvent(q);
if (mView.dispatchKeyEvent(event)) {
@frameworks/base/core/java/android/widget/TextView.java
onKeyDown(int keyCode, KeyEvent event)
int which = doKeyDown(keyCode, event, null);
if (mEditor != null && mEditor.mKeyListener != null) {
beginBatchEdit();
@frameworks/base/core/java/android/widget/Editor.java
if (mEditor != null) mEditor.beginBatchEdit();
ims.mChangedEnd = mTextView.getText().length();
mTextView.onBeginBatchEdit()
endBatchEdit();
if (handled) return KEY_DOWN_HANDLED_BY_KEY_LISTENER;
mConnection.sendKeyEvent(new KeyEvent(SystemClock.uptimeMillis(), eventTime, KeyEvent.ACTION_UP, keyCode, 0, 0, KeyCharacterMap.VIRTUAL_KEYBOARD, 0, KeyEvent.FLAG_SOFT_KEYBOARD | KeyEvent.FLAG_KEEP_TOUCH_MODE));
if (isConnected()) { mIC.sendKeyEvent(keyEvent); }
.......................................................................................................
ViewPostImeInputStage::onProcess
return processKeyEvent(q);
if (mView.dispatchKeyEvent(event)) {
@frameworks/base/core/java/android/widget/TextView.java
onKeyUp(int keyCode, KeyEvent event)
if (mEditor != null && mEditor.mKeyListener != null) { mEditor.mKeyListener.onKeyUp(this, (Editable) mText, keyCode, event) }
if (mMovement != null && mLayout != null) { mMovement.onKeyUp(this, mSpannable, keyCode, event) }
return super.onKeyUp(keyCode, event);
return FORWARD;
@packages/inputmethods/LatinIME/java/src/com/android/inputmethod/keyboard/KeyboardSwitcher.java
mKeyboardSwitcher.onEvent(event, getCurrentAutoCapsState(), getCurrentRecapitalizeState());
mState.onEvent(event, currentAutoCapsState, currentRecapitalizeState);
callListenerOnRelease(key, code, false /* withSliding */);
if (key.isEnabled()) {
@packages/inputmethods/LatinIME/java/src/com/android/inputmethod/latin/LatinIME.java
sListener.onReleaseKey(primaryCode, withSliding);
mKeyboardSwitcher.onReleaseKey(primaryCode, withSliding, getCurrentAutoCapsState(),getCurrentRecapitalizeState());
//org.mozilla.firefox
EarlyPostImeInputStage::onProcess //QueuedInputEvent{flags=DELIVER_POST_IME, hasNextQueuedEvent=true, hasInputEventReceiver=false, mEvent=KeyEvent { action=ACTION_DOWN, keyCode=KEYCODE_1, scanCode=0, metaState=0, flags=0x6, repeatCount=0, eventTime=60143, downTime=60143, deviceId=-1, source=0x0, displayId=0 }}
NativePostImeInputStage onProcess
ViewPostImeInputStage onProcess
EarlyPostImeInputStage::onProcess //QueuedInputEvent{flags=DELIVER_POST_IME, hasNextQueuedEvent=true, hasInputEventReceiver=false, mEvent=KeyEvent { action=ACTION_UP, keyCode=KEYCODE_1, scanCode=0, metaState=0, flags=0x6, repeatCount=0, eventTime=60143, downTime=60146, deviceId=-1, source=0x0, displayId=0 }}
NativePostImeInputStage onProcess
ViewPostImeInputStage onProcess