Android 5.0输入系统分析之InputDispatcher线程分析

来源:互联网 发布:mac see sheer真人试色 编辑:程序博客网 时间:2024/05/29 15:07

上编分析知道是InputReader线程唤醒了InputDispatcher线程分析,InputDispatcher线程是从dispatchOnce启动,从dispatchOnce函数进行分析。

void InputDispatcher::dispatchOnce() {        if (!haveCommandsLocked()) {             dispatchOnceInnerLocked(&nextWakeupTime);         }   if (runCommandsLockedInterruptible()) {         nextWakeupTime = LONG_LONG_MIN;     }    mLooper->pollOnce(timeoutMillis);}

调用了haveCommandsLocked,就是调用了InputDispatcher.cpp中的haveCommandsLocked函数:

bool InputDispatcher::haveCommandsLocked() const {    return !mCommandQueue.isEmpty();}

检查mCommandQueue队例是否有数据,刚进来的时候mCommandQueue队例是空的,所以接着调用dispatchOnceInnerLocked函数,也就是调用了InputDispatcher.cpp中的dispatchOnceInnerLocked函数

void InputDispatcher::dispatchOnceInnerLocked(nsecs_t* nextWakeupTime) {if (! mPendingEvent) {          mPendingEvent = mInboundQueue.dequeueAtHead();    }    switch (mPendingEvent->type) {    case EventEntry::TYPE_KEY: {        KeyEntry* typedEntry = static_cast<KeyEntry*>(mPendingEvent);        done = dispatchKeyLocked(currentTime, typedEntry, &dropReason, nextWakeupTime);        break;    }    if (done) {        if (dropReason != DROP_REASON_NOT_DROPPED) {            dropInboundEventLocked(mPendingEvent, dropReason);         }}

haveCommandsLocked函数就是从mInboundQueue队例中取出数据,然后调用了dispatchKeyLocked进行了分发,分发成功后调用了dropInboundEventLocked清空mPendingEvent等操作。具体是如何分发的,对它详细分析.调用了InputDispatcher.cpp中的dispatchKeyLocked

bool InputDispatcher::dispatchKeyLocked(nsecs_t currentTime, KeyEntry* entry,        DropReason* dropReason, nsecs_t* nextWakeupTime) {        ......    if (entry->interceptKeyResult == KeyEntry::INTERCEPT_KEY_RESULT_UNKNOWN) {        if (entry->policyFlags & POLICY_FLAG_PASS_TO_USER) {            CommandEntry* commandEntry = postCommandLocked(                    & InputDispatcher::doInterceptKeyBeforeDispatchingLockedInterruptible);            if (mFocusedWindowHandle != NULL) {                commandEntry->inputWindowHandle = mFocusedWindowHandle;            }            commandEntry->keyEntry = entry;            entry->refCount += 1;            return false;         }         ......}

刚进来entry->interceptKeyResult = INTERCEPT_KEY_RESULT_UNKNOWN,所以会走这个分支,调用postCommandLocked函数把命令加入到队例中,然后返回false,即是done = false。再看postCommandLocked函数

InputDispatcher::CommandEntry* InputDispatcher::postCommandLocked(Command command) {    CommandEntry* commandEntry = new CommandEntry(command);    mCommandQueue.enqueueAtTail(commandEntry);    return commandEntry;}

把命令加入mCommandQueue队例头,传入的参数据就是InputDispatcher::doInterceptKeyBeforeDispatchingLockedInterruptible函数,后面会用到。

返回到dispatchOnceInnerLocked调用了InputDispatcher.cpp中的runCommandsLockedInterruptible函数:

bool InputDispatcher::runCommandsLockedInterruptible() {    if (mCommandQueue.isEmpty()) {        return false;    }    do {        CommandEntry* commandEntry = mCommandQueue.dequeueAtHead();        Command command = commandEntry->command;        (this->*command)(commandEntry); // commands are implicitly 'LockedInterruptible'        commandEntry->connection.clear();        delete commandEntry;    } while (! mCommandQueue.isEmpty());    return true;}

从mCommandQueue取出数据,然后执行它,就是上面加入队例的InputDispatcher::doInterceptKeyBeforeDispatchingLockedInterruptible。那么就是调用了InputDispatcher.cpp中的doInterceptKeyBeforeDispatchingLockedInterruptible函数

void InputDispatcher::doInterceptKeyBeforeDispatchingLockedInterruptible(        CommandEntry* commandEntry) {    KeyEntry* entry = commandEntry->keyEntry;    KeyEvent event;    initializeKeyEvent(&event, entry);    mLock.unlock();    nsecs_t delay = mPolicy->interceptKeyBeforeDispatching(commandEntry->inputWindowHandle,            &event, entry->policyFlags);    mLock.lock();    if (delay < 0) {        entry->interceptKeyResult = KeyEntry::INTERCEPT_KEY_RESULT_SKIP;    } else if (!delay) {        entry->interceptKeyResult = KeyEntry::INTERCEPT_KEY_RESULT_CONTINUE;    } else {        entry->interceptKeyResult = KeyEntry::INTERCEPT_KEY_RESULT_TRY_AGAIN_LATER;        entry->interceptKeyWakeupTime = now() + delay;    }    entry->release();}

调用了mPolicy->interceptKeyBeforeDispatching函数,mPolicy是什么东东?前面《Android 5.0输入系统分析之InputReader线程分析》可知是调用了com_android_server_input_InputManagerService.cpp中
interceptKeyBeforeDispatching

nsecs_t NativeInputManager::interceptKeyBeforeDispatching(        const sp<InputWindowHandle>& inputWindowHandle,        const KeyEvent* keyEvent, uint32_t policyFlags) {     jlong delayMillis = env->CallLongMethod(mServiceObj,                    gServiceClassInfo.interceptKeyBeforeDispatching,                    inputWindowHandleObj, keyEventObj, policyFlags);             return result;}

调用了PhoneWindowManager.java中interceptKeyBeforeDispatching函数

public long interceptKeyBeforeDispatching(WindowState win, KeyEvent event, int policyFlags) {        final boolean keyguardOn = keyguardOn();        final int keyCode = event.getKeyCode();        final int repeatCount = event.getRepeatCount();        final int metaState = event.getMetaState();        final int flags = event.getFlags();        final boolean down = event.getAction() == KeyEvent.ACTION_DOWN;        final boolean canceled = event.isCanceled();        if (DEBUG_INPUT) {            Log.d(TAG, "interceptKeyTi keyCode=" + keyCode + " down=" + down + " repeatCount="                    + repeatCount + " keyguardOn=" + keyguardOn + " mHomePressed=" + mHomePressed                    + " canceled=" + canceled);        }        // If we think we might have a volume down & power key chord on the way        // but we're not sure, then tell the dispatcher to wait a little while and        // try again later before dispatching.        if (mScreenshotChordEnabled && (flags & KeyEvent.FLAG_FALLBACK) == 0) {            if (mScreenshotChordVolumeDownKeyTriggered && !mScreenshotChordPowerKeyTriggered) {                final long now = SystemClock.uptimeMillis();                final long timeoutTime = mScreenshotChordVolumeDownKeyTime                        + SCREENSHOT_CHORD_DEBOUNCE_DELAY_MILLIS;                if (now < timeoutTime) {                    return timeoutTime - now;                }            }            if (keyCode == KeyEvent.KEYCODE_VOLUME_DOWN                    && mScreenshotChordVolumeDownKeyConsumed) {                if (!down) {                    mScreenshotChordVolumeDownKeyConsumed = false;                }                return -1;            }        }        // Cancel any pending meta actions if we see any other keys being pressed between the down        // of the meta key and its corresponding up.        if (mPendingMetaAction && !KeyEvent.isMetaKey(keyCode)) {            mPendingMetaAction = false;        }        // First we always handle the home key here, so applications        // can never break it, although if keyguard is on, we do let        // it handle it, because that gives us the correct 5 second        // timeout.        if (keyCode == KeyEvent.KEYCODE_HOME) {            // If we have released the home key, and didn't do anything else            // while it was pressed, then it is time to go home!            if (!down) {                cancelPreloadRecentApps();                mHomePressed = false;                if (mHomeConsumed) {                    mHomeConsumed = false;                    return -1;                }                if (canceled) {                    Log.i(TAG, "Ignoring HOME; event canceled.");                    return -1;                }                // If an incoming call is ringing, HOME is totally disabled.                // (The user is already on the InCallUI at this point,                // and his ONLY options are to answer or reject the call.)                TelecomManager telecomManager = getTelecommService();                if (telecomManager != null && telecomManager.isRinging()) {                    Log.i(TAG, "Ignoring HOME; there's a ringing incoming call.");                    return -1;                }                // Delay handling home if a double-tap is possible.                if (mDoubleTapOnHomeBehavior != DOUBLE_TAP_HOME_NOTHING) {                    mHandler.removeCallbacks(mHomeDoubleTapTimeoutRunnable); // just in case                    mHomeDoubleTapPending = true;                    mHandler.postDelayed(mHomeDoubleTapTimeoutRunnable,                            ViewConfiguration.getDoubleTapTimeout());                    return -1;                }                handleShortPressOnHome();                return -1;            }            // If a system window has focus, then it doesn't make sense            // right now to interact with applications.            WindowManager.LayoutParams attrs = win != null ? win.getAttrs() : null;            if (attrs != null) {                final int type = attrs.type;                if (type == WindowManager.LayoutParams.TYPE_KEYGUARD_SCRIM                        || type == WindowManager.LayoutParams.TYPE_KEYGUARD_DIALOG                        || (attrs.privateFlags & PRIVATE_FLAG_KEYGUARD) != 0) {                    // the "app" is keyguard, so give it the key                    return 0;                }                final int typeCount = WINDOW_TYPES_WHERE_HOME_DOESNT_WORK.length;                for (int i=0; i<typeCount; i++) {                    if (type == WINDOW_TYPES_WHERE_HOME_DOESNT_WORK[i]) {                        // don't do anything, but also don't pass it to the app                        return -1;                    }                }            }            // Remember that home is pressed and handle special actions.            if (repeatCount == 0) {                mHomePressed = true;                if (mHomeDoubleTapPending) {                    mHomeDoubleTapPending = false;                    mHandler.removeCallbacks(mHomeDoubleTapTimeoutRunnable);                    handleDoubleTapOnHome();                } else if (mLongPressOnHomeBehavior == LONG_PRESS_HOME_RECENT_SYSTEM_UI                        || mDoubleTapOnHomeBehavior == DOUBLE_TAP_HOME_RECENT_SYSTEM_UI) {                    preloadRecentApps();                }            } else if ((event.getFlags() & KeyEvent.FLAG_LONG_PRESS) != 0) {                if (!keyguardOn) {                    handleLongPressOnHome();                }            }            return -1;        } else if (keyCode == KeyEvent.KEYCODE_MENU) {            // Hijack modified menu keys for debugging features            final int chordBug = KeyEvent.META_SHIFT_ON;            if (down && repeatCount == 0) {                if (mEnableShiftMenuBugReports && (metaState & chordBug) == chordBug) {                    Intent intent = new Intent(Intent.ACTION_BUG_REPORT);                    mContext.sendOrderedBroadcastAsUser(intent, UserHandle.CURRENT,                            null, null, null, 0, null, null);                    return -1;                } else if (SHOW_PROCESSES_ON_ALT_MENU &&                        (metaState & KeyEvent.META_ALT_ON) == KeyEvent.META_ALT_ON) {                    Intent service = new Intent();                    service.setClassName(mContext, "com.android.server.LoadAverageService");                    ContentResolver res = mContext.getContentResolver();                    boolean shown = Settings.Global.getInt(                            res, Settings.Global.SHOW_PROCESSES, 0) != 0;                    if (!shown) {                        mContext.startService(service);                    } else {                        mContext.stopService(service);                    }                    Settings.Global.putInt(                            res, Settings.Global.SHOW_PROCESSES, shown ? 0 : 1);                    return -1;                }            }        } else if (keyCode == KeyEvent.KEYCODE_SEARCH) {            if (down) {                if (repeatCount == 0) {                    mSearchKeyShortcutPending = true;                    mConsumeSearchKeyUp = false;                }            } else {                mSearchKeyShortcutPending = false;                if (mConsumeSearchKeyUp) {                    mConsumeSearchKeyUp = false;                    return -1;                }            }            return 0;        } else if (keyCode == KeyEvent.KEYCODE_APP_SWITCH) {            if (!keyguardOn) {                if (down && repeatCount == 0) {                    preloadRecentApps();                } else if (!down) {                    toggleRecentApps();                }            }            return -1;        } else if (keyCode == KeyEvent.KEYCODE_ASSIST) {            if (down) {                if (repeatCount == 0) {                    mAssistKeyLongPressed = false;                } else if (repeatCount == 1) {                    mAssistKeyLongPressed = true;                    if (!keyguardOn) {                         launchAssistLongPressAction();                    }                }            } else {                if (mAssistKeyLongPressed) {                    mAssistKeyLongPressed = false;                } else {                    if (!keyguardOn) {                        launchAssistAction();                    }                }            }            return -1;        } else if (keyCode == KeyEvent.KEYCODE_VOICE_ASSIST) {            if (!down) {                Intent voiceIntent;                if (!keyguardOn) {                    voiceIntent = new Intent(RecognizerIntent.ACTION_WEB_SEARCH);                } else {                    voiceIntent = new Intent(RecognizerIntent.ACTION_VOICE_SEARCH_HANDS_FREE);                    voiceIntent.putExtra(RecognizerIntent.EXTRA_SECURE, true);                }                startActivityAsUser(voiceIntent, UserHandle.CURRENT_OR_SELF);            }        } else if (keyCode == KeyEvent.KEYCODE_SYSRQ) {            if (down && repeatCount == 0) {                mHandler.post(mScreenshotRunnable);            }            return -1;        } else if (keyCode == KeyEvent.KEYCODE_BRIGHTNESS_UP                || keyCode == KeyEvent.KEYCODE_BRIGHTNESS_DOWN) {            if (down) {                int direction = keyCode == KeyEvent.KEYCODE_BRIGHTNESS_UP ? 1 : -1;                // Disable autobrightness if it's on                int auto = Settings.System.getIntForUser(                        mContext.getContentResolver(),                        Settings.System.SCREEN_BRIGHTNESS_MODE,                        Settings.System.SCREEN_BRIGHTNESS_MODE_MANUAL,                        UserHandle.USER_CURRENT_OR_SELF);                if (auto != 0) {                    Settings.System.putIntForUser(mContext.getContentResolver(),                            Settings.System.SCREEN_BRIGHTNESS_MODE,                            Settings.System.SCREEN_BRIGHTNESS_MODE_MANUAL,                            UserHandle.USER_CURRENT_OR_SELF);                }                int min = mPowerManager.getMinimumScreenBrightnessSetting();                int max = mPowerManager.getMaximumScreenBrightnessSetting();                int step = (max - min + BRIGHTNESS_STEPS - 1) / BRIGHTNESS_STEPS * direction;                int brightness = Settings.System.getIntForUser(mContext.getContentResolver(),                        Settings.System.SCREEN_BRIGHTNESS,                        mPowerManager.getDefaultScreenBrightnessSetting(),                        UserHandle.USER_CURRENT_OR_SELF);                brightness += step;                // Make sure we don't go beyond the limits.                brightness = Math.min(max, brightness);                brightness = Math.max(min, brightness);                Settings.System.putIntForUser(mContext.getContentResolver(),                        Settings.System.SCREEN_BRIGHTNESS, brightness,                        UserHandle.USER_CURRENT_OR_SELF);                startActivityAsUser(new Intent(Intent.ACTION_SHOW_BRIGHTNESS_DIALOG),                        UserHandle.CURRENT_OR_SELF);            }            return -1;        } else if (KeyEvent.isMetaKey(keyCode)) {            if (down) {                mPendingMetaAction = true;            } else if (mPendingMetaAction) {                launchAssistAction(Intent.EXTRA_ASSIST_INPUT_HINT_KEYBOARD);            }            return -1;        }        // Shortcuts are invoked through Search+key, so intercept those here        // Any printing key that is chorded with Search should be consumed        // even if no shortcut was invoked.  This prevents text from being        // inadvertently inserted when using a keyboard that has built-in macro        // shortcut keys (that emit Search+x) and some of them are not registered.        if (mSearchKeyShortcutPending) {            final KeyCharacterMap kcm = event.getKeyCharacterMap();            if (kcm.isPrintingKey(keyCode)) {                mConsumeSearchKeyUp = true;                mSearchKeyShortcutPending = false;                if (down && repeatCount == 0 && !keyguardOn) {                    Intent shortcutIntent = mShortcutManager.getIntent(kcm, keyCode, metaState);                    if (shortcutIntent != null) {                        shortcutIntent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK);                        try {                            startActivityAsUser(shortcutIntent, UserHandle.CURRENT);                        } catch (ActivityNotFoundException ex) {                            Slog.w(TAG, "Dropping shortcut key combination because "                                    + "the activity to which it is registered was not found: "                                    + "SEARCH+" + KeyEvent.keyCodeToString(keyCode), ex);                        }                    } else {                        Slog.i(TAG, "Dropping unregistered shortcut key combination: "                                + "SEARCH+" + KeyEvent.keyCodeToString(keyCode));                    }                }                return -1;            }        }        // Invoke shortcuts using Meta.        if (down && repeatCount == 0 && !keyguardOn                && (metaState & KeyEvent.META_META_ON) != 0) {            final KeyCharacterMap kcm = event.getKeyCharacterMap();            if (kcm.isPrintingKey(keyCode)) {                Intent shortcutIntent = mShortcutManager.getIntent(kcm, keyCode,                        metaState & ~(KeyEvent.META_META_ON                                | KeyEvent.META_META_LEFT_ON | KeyEvent.META_META_RIGHT_ON));                if (shortcutIntent != null) {                    shortcutIntent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK);                    try {                        startActivityAsUser(shortcutIntent, UserHandle.CURRENT);                    } catch (ActivityNotFoundException ex) {                        Slog.w(TAG, "Dropping shortcut key combination because "                                + "the activity to which it is registered was not found: "                                + "META+" + KeyEvent.keyCodeToString(keyCode), ex);                    }                    return -1;                }            }        }        // Handle application launch keys.        if (down && repeatCount == 0 && !keyguardOn) {            String category = sApplicationLaunchKeyCategories.get(keyCode);            if (category != null) {                Intent intent = Intent.makeMainSelectorActivity(Intent.ACTION_MAIN, category);                intent.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK);                try {                    startActivityAsUser(intent, UserHandle.CURRENT);                } catch (ActivityNotFoundException ex) {                    Slog.w(TAG, "Dropping application launch key because "                            + "the activity to which it is registered was not found: "                            + "keyCode=" + keyCode + ", category=" + category, ex);                }                return -1;            }        }        // Display task switcher for ALT-TAB.        if (down && repeatCount == 0 && keyCode == KeyEvent.KEYCODE_TAB) {            if (mRecentAppsHeldModifiers == 0 && !keyguardOn) {                final int shiftlessModifiers = event.getModifiers() & ~KeyEvent.META_SHIFT_MASK;                if (KeyEvent.metaStateHasModifiers(shiftlessModifiers, KeyEvent.META_ALT_ON)) {                    mRecentAppsHeldModifiers = shiftlessModifiers;                    showRecentApps(true);                    return -1;                }            }        } else if (!down && mRecentAppsHeldModifiers != 0                && (metaState & mRecentAppsHeldModifiers) == 0) {            mRecentAppsHeldModifiers = 0;            hideRecentApps(true, false);        }        // Handle keyboard language switching.        if (down && repeatCount == 0                && (keyCode == KeyEvent.KEYCODE_LANGUAGE_SWITCH                        || (keyCode == KeyEvent.KEYCODE_SPACE                                && (metaState & KeyEvent.META_CTRL_MASK) != 0))) {            int direction = (metaState & KeyEvent.META_SHIFT_MASK) != 0 ? -1 : 1;            mWindowManagerFuncs.switchKeyboardLayout(event.getDeviceId(), direction);            return -1;        }        if (mLanguageSwitchKeyPressed && !down                && (keyCode == KeyEvent.KEYCODE_LANGUAGE_SWITCH                        || keyCode == KeyEvent.KEYCODE_SPACE)) {            mLanguageSwitchKeyPressed = false;            return -1;        }        if (isValidGlobalKey(keyCode)                && mGlobalKeyManager.handleGlobalKey(mContext, keyCode, event)) {//GlobalKey广播            return -1;        }        // Reserve all the META modifier combos for system behavior        if ((metaState & KeyEvent.META_META_ON) != 0) {            return -1;        }        // Let the application handle the key.        return 0;    }

此函数是对于系统按键处理(比如:KEYCODE_MENU)和GlobalKey处理,都是返回-1.其它返回0.

 if (delay < 0) {        entry->interceptKeyResult = KeyEntry::INTERCEPT_KEY_RESULT_SKIP;    } else if (!delay) {        entry->interceptKeyResult = KeyEntry::INTERCEPT_KEY_RESULT_CONTINUE;    } else {        entry->interceptKeyResult = KeyEntry::INTERCEPT_KEY_RESULT_TRY_AGAIN_LATER;        entry->interceptKeyWakeupTime = now() + delay;    }

检查按键是还INTERCEPT_KEY_RESULT_SKIP还是INTERCEPT_KEY_RESULT_CONTINUE。上面分析知道对于系统按键(比如:KEYCODE_MENU)和GlobalKey都是INTERCEPT_KEY_RESULT_SKIP,直接处理的,其它会传给APP处理。InputDispatcher::runCommandsLockedInterruptible()处理完后,返回结果是true,那么 nextWakeupTime = LONG_LONG_MIN;也就是mLooper->pollOnce(timeoutMillis);不会等待数据 ,直接执行InputDispatcher::dispatchOnce() 。这里又从新开始分析InputDispatcher::dispatchOnce()函数

void InputDispatcher::dispatchOnce() {    nsecs_t nextWakeupTime = LONG_LONG_MAX;    {        if (!haveCommandsLocked()) {             dispatchOnceInnerLocked(&nextWakeupTime);         }    if (runCommandsLockedInterruptible()) {        nextWakeupTime = LONG_LONG_MIN;    }    mLooper->pollOnce(timeoutMillis);}

调用了haveCommandsLocked检看是否有命令,由于执行了命令,haveCommandsLocked是空的,所以会再次调用dispatchOnceInnerLocked,调用过程也是一样的,不同的点是InputDispatcher::dispatchKeyLocked中的

bool InputDispatcher::dispatchKeyLocked(nsecs_t currentTime, KeyEntry* entry,        DropReason* dropReason, nsecs_t* nextWakeupTime) {    Vector<InputTarget> inputTargets;    int32_t injectionResult = findFocusedWindowTargetsLocked(currentTime,            entry, inputTargets, nextWakeupTime);    if (injectionResult == INPUT_EVENT_INJECTION_PENDING) {        return false;    }    setInjectionResultLocked(entry, injectionResult);    if (injectionResult != INPUT_EVENT_INJECTION_SUCCEEDED) {        return true;    }    addMonitoringTargetsLocked(inputTargets);    dispatchEventLocked(currentTime, entry, inputTargets);    return true;}这一次就是搜索焦点窗口,找到后调用InputDispatcher.cpp中的dispatchEventLocked进行数据分发。void InputDispatcher::dispatchEventLocked(nsecs_t currentTime,        EventEntry* eventEntry, const Vector<InputTarget>& inputTargets) {    for (size_t i = 0; i < inputTargets.size(); i++) {        const InputTarget& inputTarget = inputTargets.itemAt(i);        ssize_t connectionIndex = getConnectionIndexLocked(inputTarget.inputChannel);        if (connectionIndex >= 0) {            sp<Connection> connection = mConnectionsByFd.valueAt(connectionIndex);            prepareDispatchCycleLocked(currentTime, connection, eventEntry, &inputTarget);        }     }

从目标窗口中找到connection ,然后调用InputDispatcher.cpp中的prepareDispatchCycleLocked把数据分发。

void InputDispatcher::enqueueDispatchEntriesLocked(nsecs_t currentTime,        const sp<Connection>& connection, EventEntry* eventEntry, const InputTarget* inputTarget) {    bool wasEmpty = connection->outboundQueue.isEmpty();    // Enqueue dispatch entries for the requested modes.    enqueueDispatchEntryLocked(connection, eventEntry, inputTarget,            InputTarget::FLAG_DISPATCH_AS_HOVER_EXIT);    enqueueDispatchEntryLocked(connection, eventEntry, inputTarget,            InputTarget::FLAG_DISPATCH_AS_OUTSIDE);    enqueueDispatchEntryLocked(connection, eventEntry, inputTarget,            InputTarget::FLAG_DISPATCH_AS_HOVER_ENTER);    enqueueDispatchEntryLocked(connection, eventEntry, inputTarget,            InputTarget::FLAG_DISPATCH_AS_IS);    enqueueDispatchEntryLocked(connection, eventEntry, inputTarget,            InputTarget::FLAG_DISPATCH_AS_SLIPPERY_EXIT);    enqueueDispatchEntryLocked(connection, eventEntry, inputTarget,            InputTarget::FLAG_DISPATCH_AS_SLIPPERY_ENTER);    // If the outbound queue was previously empty, start the dispatch cycle going.    if (wasEmpty && !connection->outboundQueue.isEmpty()) {        startDispatchCycleLocked(currentTime, connection);    }}

最后调用了InputDispatcher.cpp中的startDispatchCycleLocked把数据分发。

void InputDispatcher::startDispatchCycleLocked(nsecs_t currentTime,        const sp<Connection>& connection) {    while (connection->status == Connection::STATUS_NORMAL            && !connection->outboundQueue.isEmpty()) {        DispatchEntry* dispatchEntry = connection->outboundQueue.head;        dispatchEntry->deliveryTime = currentTime;        // Publish the event.        status_t status;        EventEntry* eventEntry = dispatchEntry->eventEntry;        switch (eventEntry->type) {        case EventEntry::TYPE_KEY: {            KeyEntry* keyEntry = static_cast<KeyEntry*>(eventEntry);            // Publish the key event.            status = connection->inputPublisher.publishKeyEvent(dispatchEntry->seq,                    keyEntry->deviceId, keyEntry->source,                    dispatchEntry->resolvedAction, dispatchEntry->resolvedFlags,                    keyEntry->keyCode, keyEntry->scanCode,                    keyEntry->metaState, keyEntry->repeatCount, keyEntry->downTime,                    keyEntry->eventTime);            break;        }    }}

比如按键类,调用了connection->inputPublisher.publishKeyEvent函数

status_t InputPublisher::publishKeyEvent(        uint32_t seq,        int32_t deviceId,        int32_t source,        int32_t action,        int32_t flags,        int32_t keyCode,        int32_t scanCode,        int32_t metaState,        int32_t repeatCount,        nsecs_t downTime,        nsecs_t eventTime) {    if (!seq) {        ALOGE("Attempted to publish a key event with sequence number 0.");        return BAD_VALUE;    }    InputMessage msg;    msg.header.type = InputMessage::TYPE_KEY;    msg.body.key.seq = seq;    msg.body.key.deviceId = deviceId;    msg.body.key.source = source;    msg.body.key.action = action;    msg.body.key.flags = flags;    msg.body.key.keyCode = keyCode;    msg.body.key.scanCode = scanCode;    msg.body.key.metaState = metaState;    msg.body.key.repeatCount = repeatCount;    msg.body.key.downTime = downTime;    msg.body.key.eventTime = eventTime;    return mChannel->sendMessage(&msg);}

然后调用mChannel->sendMessage(&msg);把数据发送给APP。