Android InputManagerService分析(基于Android 8.0)

1 InputManagerService简介

InputManagerService(IMS)创建过程和其他服务类似,都由SystemServer启动,java层的IMS实际上是对native层NativeInputManager的包装。nativeInit函数中通过jni创建NativeInputManager对象,在NativeInputManager中创建了EventHub和InputManager对象,IMS在native层的实现主体是EventHub和InputManager。

inputManager = new InputManagerService(context);
inputManager.setWindowManagerCallbacks(wm.getInputMonitor());
// step1, 开启事件接收和派发线程
inputManager.start();
public InputManagerService(Context context) {
    this.mContext = context;
    this.mHandler = new InputManagerHandler(DisplayThread.get().getLooper());
    // step2, 构造natvie InputManager对象
    mPtr = nativeInit(this, mContext, mHandler.getLooper().getQueue());
    LocalServices.addService(InputManagerInternal.class, new LocalService());
}
1.1 com_android_server_input_InputManagerService.cpp
static jlong nativeInit(JNIEnv* env, jclass /* clazz */,
        jobject serviceObj, jobject contextObj, jobject messageQueueObj) {
    NativeInputManager* im = new NativeInputManager(contextObj, serviceObj,
            messageQueue->getLooper());
    im->incStrong(0);
    return reinterpret_cast<jlong>(im);
}
1.2 NativeInputManager
  • EventHub:
    监听/dev/input/下的设备节点,监听输入事件的上报,输入设备的插拔.如果有事件处理,则交给InputReader处理
  • InputReaderThread线程:
    EventHub监听/dev/input/下的设备节点,监听输入事件的上报,输入设备的插拔.前期处理后,将事件投放到mInboundQueue队列中交给InputDispatcherThread处理
  • InputDispatcherThread线程:
    从mInboundQueue队列中取出事件,通过findFocusedWindowTargetsLocked和findTouchedWindowTargetsLocked找到对应接收事件的窗口,将事件放入到接收窗口中的outboundQueue,当派发事件时,从outboundQueue队列中移除,将事件添加到waitQueue队列, 事件处理完成,则将事件从waitQueue队列中删除,事件处理完成,发送下一个事件
NativeInputManager::NativeInputManager(jobject contextObj,
        jobject serviceObj, const sp<Looper>& looper) :
        mLooper(looper), mInteractive(true) {
    JNIEnv* env = jniEnv();

    sp<EventHub> eventHub = new EventHub();
    mInputManager = new InputManager(eventHub, this, this);
}
1.3 InputManager

InputManager中创建了2个两个线程InputReaderThread和InputDispatcherThread。

InputManager::InputManager(
        const sp<EventHubInterface>& eventHub,
        const sp<InputReaderPolicyInterface>& readerPolicy,
        const sp<InputDispatcherPolicyInterface>& dispatcherPolicy) {
    mDispatcher = new InputDispatcher(dispatcherPolicy);
    // step1, 把mDispatcher传给了InputReader,InputDispatcher实现了InputListenerInterface接口
    mReader = new InputReader(eventHub, readerPolicy, mDispatcher);
    // step2, 初始化线程对象
    initialize();
}
void InputManager::initialize() {
    // 创建线程对象
    mReaderThread = new InputReaderThread(mReader);
    mDispatcherThread = new InputDispatcherThread(mDispatcher);
}
1.4 启动线程
static void nativeStart(JNIEnv* env, jclass /* clazz */, jlong ptr) {
    NativeInputManager* im = reinterpret_cast<NativeInputManager*>(ptr);

    status_t result = im->getInputManager()->start();
    if (result) {
        jniThrowRuntimeException(env, "Input manager could not be started.");
    }
}
status_t InputManager::start() {
    // 启动线程
    status_t result = mDispatcherThread->run("InputDispatcher", PRIORITY_URGENT_DISPLAY);
    result = mReaderThread->run("InputReader", PRIORITY_URGENT_DISPLAY);
    return OK;
}

2 InputReader分析

InputReader线程循环调用loopOnce函数,通过EventHub的getEvents函数不断获取系统中的输入事件,前期的加工处理(将对应的机器码映射成对应的keycode),然后添加到QueuedInputListener的mArgsQueue队列中,然后通过QueuedInputListener的flush函数逐一存放到mInboundQueue队列中

InputReader::InputReader(const sp<EventHubInterface>& eventHub,
        const sp<InputReaderPolicyInterface>& policy,
        const sp<InputListenerInterface>& listener) :
        mContext(this), mEventHub(eventHub), mPolicy(policy),
        mGlobalMetaState(0), mGeneration(1),
        mDisableVirtualKeysTimeout(LLONG_MIN), mNextTimeout(LLONG_MAX),
        mConfigurationChangesToRefresh(0) {
    // listener为InputDispatcher对象
    mQueuedListener = new QueuedInputListener(listener);
}
2.1 InputReader::loopOnce
void InputReader::loopOnce() {
    // step1, 获取输入事件
    size_t count = mEventHub->getEvents(timeoutMillis, mEventBuffer, EVENT_BUFFER_SIZE);

    { // acquire lock
        AutoMutex _l(mLock);
        if (count) {
            // step2, 处理输入事件
            processEventsLocked(mEventBuffer, count);
        }
    } // release lock

    // step3, 将输入事件交给InputDispatcher处理
    mQueuedListener->flush();
}
2.2 InputReader::processEventsLocked

processEventsLocked主要功能为输入事件的前期处理和输入设备的插拔处理,我们主要分析输入事件的处理

void InputReader::processEventsLocked(const RawEvent* rawEvents, size_t count) {
    for (const RawEvent* rawEvent = rawEvents; count;) {
        if (type < EventHubInterface::FIRST_SYNTHETIC_EVENT) {
            int32_t deviceId = rawEvent->deviceId;
            // 输入事件的处理
            processEventsForDeviceLocked(deviceId, rawEvent, batchSize);
        } else {
            switch (rawEvent->type) {
            case EventHubInterface::DEVICE_ADDED:
                // 输入设备添加
                addDeviceLocked(rawEvent->when, rawEvent->deviceId);
                break;
            case EventHubInterface::DEVICE_REMOVED:
                // 输入设备移除
                removeDeviceLocked(rawEvent->when, rawEvent->deviceId);
                break;
            default:
                ALOG_ASSERT(false); // can't happen
                break;
            }
        }
        count -= batchSize;
        rawEvent += batchSize;
    }
}
2.3 InputReader::processEventsForDeviceLocked

直接调用InputDevice的process函数,InputDevice中有个InputMapper类型的mMappers数组,根据输入设备的不同,map不一样,process最终调用对应的InputMapper的process函数
常见的InputMapper类型

// 按键事件相关
KeyboardInputMapper
// 触摸事件相关
MultiTouchInputMapper
void InputReader::processEventsForDeviceLocked(int32_t deviceId,
        const RawEvent* rawEvents, size_t count) {
    InputDevice* device = mDevices.valueAt(deviceIndex);
    if (device->isIgnored()) {
        //ALOGD("Discarding event for ignored deviceId %d.", deviceId);
        return;
    }
    // 调用InputDevice的process函数
    device->process(rawEvents, count);
}
2.4 InputDevice::process
void InputDevice::process(const RawEvent* rawEvents, size_t count) {
    size_t numMappers = mMappers.size();
    for (const RawEvent* rawEvent = rawEvents; count--; rawEvent++) {
        for (size_t i = 0; i < numMappers; i++) {
            InputMapper* mapper = mMappers[i];
            // 调用对应mapper的process函数
            mapper->process(rawEvent);
        }
    }
}
2.5 KeyboardInputMapper

接下来以KeyboardInputMapper来分析,和其他InputMapper处理流程相似
process函数中发现真正处理事件的函数为processKey,接下来继续分析processKey函数,构造NotifyKeyArgs对象,调用getListener()->notifyKey(&args), 其中getListener()为QueuedInputListener, 分析QueuedInputListener的notifyKey函数发现,将NotifyKeyArgs添加到QueuedInputListener的mArgsQueue队列中,后续通过flush函数将事件传递给InputDispatcher处理

void KeyboardInputMapper::process(const RawEvent* rawEvent) {
    switch (rawEvent->type) {
    case EV_KEY: {
        int32_t scanCode = rawEvent->code;
        int32_t usageCode = mCurrentHidUsage;
        mCurrentHidUsage = 0;

        if (isKeyboardOrGamepadKey(scanCode)) {
            processKey(rawEvent->when, rawEvent->value != 0, scanCode, usageCode);
        }
        break;
    }
    }
}
void KeyboardInputMapper::processKey(nsecs_t when, bool down, int32_t scanCode,
        int32_t usageCode) {

    NotifyKeyArgs args(when, getDeviceId(), mSource, policyFlags,
            down ? AKEY_EVENT_ACTION_DOWN : AKEY_EVENT_ACTION_UP,
            AKEY_EVENT_FLAG_FROM_SYSTEM, keyCode, scanCode, keyMetaState, downTime);
    // getListener为QueuedInputListener
    getListener()->notifyKey(&args);
}
void QueuedInputListener::notifyKey(const NotifyKeyArgs* args) {
    mArgsQueue.push(new NotifyKeyArgs(*args));
}
void QueuedInputListener::flush() {
    size_t count = mArgsQueue.size();
    for (size_t i = 0; i < count; i++) {
        NotifyArgs* args = mArgsQueue[i];
        // 调用NotifyArgs的notify函数
        args->notify(mInnerListener);
        delete args;
    }
    mArgsQueue.clear();
}
void NotifyKeyArgs::notify(const sp<InputListenerInterface>& listener) const {
    // listener为InputDispatcher
    listener->notifyKey(this);
}
2.6 InputDispatcher::notifyKey

调用PhoneWindowManager的interceptKeyBeforeQueueing或interceptMotionBeforeQueueing函数,判断是否需要将此按键事件或者触摸事件进行拦截,如果不需要拦截,则将事件添加到mInboundQueue中, 供InputDispatcher使用。

void InputDispatcher::notifyKey(const NotifyKeyArgs* args) {
    // step1, 调用PhoneWindowManager的interceptKeyBeforeQueueing函数,是否需要将此事件拦截
    mPolicy->interceptKeyBeforeQueueing(&event, /*byref*/ policyFlags);

    bool needWake;
    { // acquire lock
        mLock.lock();
        int32_t repeatCount = 0;
        KeyEntry* newEntry = new KeyEntry(args->eventTime,
                args->deviceId, args->source, policyFlags,
                args->action, flags, keyCode, args->scanCode,
                metaState, repeatCount, args->downTime);
        // step2, 将KeyEntry入mInboundQueue队列
        needWake = enqueueInboundEventLocked(newEntry);
        mLock.unlock();
    } // release lock

    // step3, 是否需要唤醒InputDispatcher线程
    if (needWake) {
        mLooper->wake();
    }
}
2.7 InputDispatcher::notifyMotion
void InputDispatcher::notifyMotion(const NotifyMotionArgs* args) {
    // step1, 调用PhoneWindowManager的interceptMotionBeforeQueueing函数,是否需要将此事件拦截
    mPolicy->interceptMotionBeforeQueueing(args->eventTime, /*byref*/ policyFlags);

    bool needWake;
    { // acquire lock
        mLock.lock();
        // Just enqueue a new motion event.
        MotionEntry* newEntry = new MotionEntry(args->eventTime,
                args->deviceId, args->source, policyFlags,
                args->action, args->actionButton, args->flags,
                args->metaState, args->buttonState,
                args->edgeFlags, args->xPrecision, args->yPrecision, args->downTime,
                args->displayId,
                args->pointerCount, args->pointerProperties, args->pointerCoords, 0, 0);
        // step2, 将MotionEntry入mInboundQueue队列
        needWake = enqueueInboundEventLocked(newEntry);
        mLock.unlock();
    } // release lock

    // step3, 是否需要唤醒InputDispatcher线程
    if (needWake) {
        mLooper->wake();
    }
}
2.8 InputDispatcher::enqueueInboundEventLocked
bool InputDispatcher::enqueueInboundEventLocked(EventEntry* entry) {
    bool needWake = mInboundQueue.isEmpty();
    // 将事件添加到mInboundQueue队列,供InputDispatcher使用
    mInboundQueue.enqueueAtTail(entry);
}
2.9 InputReader处理事件流程:
1 loopOnce
    2 mEventHub->getEvents(timeoutMillis, mEventBuffer, EVENT_BUFFER_SIZE);
    2 processEventsLocked
        3 processEventsForDeviceLocked
            4 device->process(rawEvents, count);
                5 mapper->process(rawEvent);
                    6 processKey
                        7 getListener()->notifyKey(&args);
    2 mQueuedListener->flush();        
        3 args->notify(mInnerListener);
            4 listener->notifyKey(this);
                5 interceptKeyBeforeQueueing
                5 enqueueInboundEventLocked

3 InputDispatcher分析

threadLoop函数中循环调用dispatchOnce,haveCommandsLocked函数根据mCommandQueue队列中是否存在事件队列,如果没有事件处理,则准备处理下一个事件,接着调用dispatchOnceInnerLocked做接下来的动作

void InputDispatcher::dispatchOnce() {
    nsecs_t nextWakeupTime = LONG_LONG_MAX;
    { // acquire lock
        // Run a dispatch loop if there are no pending commands.
        // The dispatch loop might enqueue commands to run afterwards.
        // 判断mCommandQueue中是否有事件正在派发
        if (!haveCommandsLocked()) {
            // 准备处理下一个事件
            dispatchOnceInnerLocked(&nextWakeupTime);
        }


    } // release lock
}
3.1 InputDispatcher::dispatchOnceInnerLocked

dispatchOnceInnerLocked函数根据输入事件的类型不同走不同的流程,按键事件和输入事件派发的流程大致相同,我们以按键事件流程来分析,

void InputDispatcher::dispatchOnceInnerLocked(nsecs_t* nextWakeupTime) {
    switch (mPendingEvent->type) {
        case EventEntry::TYPE_KEY: {
            // step1, 按键事件处理
            KeyEntry* typedEntry = static_cast<KeyEntry*>(mPendingEvent);
            done = dispatchKeyLocked(currentTime, typedEntry, &dropReason, nextWakeupTime);
            break;
        }
        case EventEntry::TYPE_MOTION: {
            // step2, 触摸事件处理
            MotionEntry* typedEntry = static_cast<MotionEntry*>(mPendingEvent);
            done = dispatchMotionLocked(currentTime, typedEntry,
                    &dropReason, nextWakeupTime);
            break;
        }
    }

    // 处理完的收尾工作
    if (done) {
        mLastDropReason = dropReason;
        releasePendingEventLocked();
    }
}
3.2 InputDispatcher::dispatchKeyLocked

KeyEntry第一次进来没有被处理时,entry->interceptKeyResult为KeyEntry::INTERCEPT_KEY_RESULT_UNKNOWN,首先调用InputDispatcher::doInterceptKeyBeforeDispatchingLockedInterruptible函数,内部会调用PhoneWindowManager的interceptKeyBeforeDispatching来判断此事件是否需要拦截,不拦截则继续处理。findFocusedWindowTargetsLocked函数找到接收输入事件的窗口,保存在inputTargets中, dispatchEventLocked函数做后续的处理

bool InputDispatcher::dispatchKeyLocked(nsecs_t currentTime, KeyEntry* entry,
        DropReason* dropReason, nsecs_t* nextWakeupTime) {
    // Preprocessing.
    // Give the policy a chance to intercept the key.
    if (entry->interceptKeyResult == KeyEntry::INTERCEPT_KEY_RESULT_UNKNOWN) {
        if (entry->policyFlags & POLICY_FLAG_PASS_TO_USER) {
            // step1, 调用PhoneWindowManager的interceptKeyBeforeDispatching来判断此事件是否需要拦截
            CommandEntry* commandEntry = postCommandLocked(
                    & InputDispatcher::doInterceptKeyBeforeDispatchingLockedInterruptible);
            if (mFocusedWindowHandle != NULL) {
                commandEntry->inputWindowHandle = mFocusedWindowHandle;
            }
            commandEntry->keyEntry = entry;
            entry->refCount += 1;
            // step2, 直接返回,等待postCommandLocked队列处理完
            return false; // wait for the command to run
        } else {
            entry->interceptKeyResult = KeyEntry::INTERCEPT_KEY_RESULT_CONTINUE;
        }
    } else if (entry->interceptKeyResult == KeyEntry::INTERCEPT_KEY_RESULT_SKIP) {
        if (*dropReason == DROP_REASON_NOT_DROPPED) {
            *dropReason = DROP_REASON_POLICY;
        }
    }

    // step3, 如果放弃事件,则不往下处理
    if (*dropReason != DROP_REASON_NOT_DROPPED) {
        setInjectionResultLocked(entry, *dropReason == DROP_REASON_POLICY
                ? INPUT_EVENT_INJECTION_SUCCEEDED : INPUT_EVENT_INJECTION_FAILED);
        return true;
    }

    // step4,找到对应接收事件的inputTargets
    Vector<InputTarget> inputTargets;
    int32_t injectionResult = findFocusedWindowTargetsLocked(currentTime,
            entry, inputTargets, nextWakeupTime);
    if (injectionResult == INPUT_EVENT_INJECTION_PENDING) {
        return false;
    }

    // step5, 派发事件
    dispatchEventLocked(currentTime, entry, inputTargets);
    return true;
}
3.3 InputDispatcher::dispatchEventLocked

getConnectionIndexLocked获取输入窗口对应的socket连接,稍后我们再来分析App窗口是如何和IMS之间建立连接的,connectionIndex大于0说明存在对应的连接通道,接着调用了prepareDispatchCycleLocked函数。

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);
        }
    }
}
3.4 InputDispatcher::prepareDispatchCycleLocked
void InputDispatcher::prepareDispatchCycleLocked(nsecs_t currentTime,
        const sp<Connection>& connection, EventEntry* eventEntry, const InputTarget* inputTarget) {
    // Not splitting.  Enqueue dispatch entries for the event as is.
    // 将输入事件放入outboundQueue队列中
    enqueueDispatchEntriesLocked(currentTime, connection, eventEntry, inputTarget);
}
3.5 InputDispatcher::enqueueDispatchEntriesLocked

根据InputTarget类型,确定事件是否添加到到outboundQueue中,如果outboundQueue不为空,则调用startDispatchCycleLocked将事件信息派发给对应的app窗口,等待app发送处理结束的消息

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.
    // 如果outboundQueue有数据,派发
    if (wasEmpty && !connection->outboundQueue.isEmpty()) {
        startDispatchCycleLocked(currentTime, connection);
    }
}
3.6 InputDispatcher::startDispatchCycleLocked

通过connection->inputPublisher的publishKeyEvent或者publishMotionEvent派发给指定app窗口,最终会回调ViewRootImpl中内部类WindowInputEventReceiver中的onInputEvent函数,App中的事件流程暂时不分析。然后将派发的事件从outboundQueue队列中移除,添加到waitQueue队列中,如果app事件处理完成,会回调InputDispatcher的handleReceiveCallback函数,将事件从waitQueue中移除,事件处理结束,接着派发下一个事件

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.
                // step1, 将按键事件发送到app窗口
                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;
            }

            case EventEntry::TYPE_MOTION: {
                MotionEntry* motionEntry = static_cast<MotionEntry*>(eventEntry);
                // Publish the motion event.
                // step2, 将触摸事件发送到app窗口
                status = connection->inputPublisher.publishMotionEvent(dispatchEntry->seq,
                        motionEntry->deviceId, motionEntry->source,
                        dispatchEntry->resolvedAction, motionEntry->actionButton,
                        dispatchEntry->resolvedFlags, motionEntry->edgeFlags,
                        motionEntry->metaState, motionEntry->buttonState,
                        xOffset, yOffset, motionEntry->xPrecision, motionEntry->yPrecision,
                        motionEntry->downTime, motionEntry->eventTime,
                        motionEntry->pointerCount, motionEntry->pointerProperties,
                        usingCoords);
                break;
            }
        }

        // Re-enqueue the event on the wait queue.
        // step3, 从outboundQueue从移除
        connection->outboundQueue.dequeue(dispatchEntry);
        traceOutboundQueueLengthLocked(connection);
        // step4, 添加到waitQueue队列中
        connection->waitQueue.enqueueAtTail(dispatchEntry);
    }
}
3.7 InputDispatcher::handleReceiveCallback

handleReceiveCallback当app窗口将事件消费完后,会发一个消息给InputDispatcher, 回调handleReceiveCallback

int InputDispatcher::handleReceiveCallback(int fd, int events, void* data) {
    InputDispatcher* d = static_cast<InputDispatcher*>(data);

    { // acquire lock
        std::scoped_lock _l(d->mLock);
        bool notify;
        sp<Connection> connection = d->mConnectionsByFd.valueAt(connectionIndex);
        if (!(events & (ALOOPER_EVENT_ERROR | ALOOPER_EVENT_HANGUP))) {
            if (!(events & ALOOPER_EVENT_INPUT)) {
                ALOGW("channel '%s' ~ Received spurious callback for unhandled poll event.  "
                        "events=0x%x", connection->getInputChannelName().c_str(), events);
                return 1;
            }

            nsecs_t currentTime = now();
            bool gotOne = false;
            status_t status;
            for (;;) {
                uint32_t seq;
                bool handled;
                // step1, 接收按键事件处理消息
                status = connection->inputPublisher.receiveFinishedSignal(&seq, &handled);
                if (status) {
                    break;
                }
                // step2, 事件派发完成相关处理
                d->finishDispatchCycleLocked(currentTime, connection, seq, handled);
                gotOne = true;
            }
            if (gotOne) {
                d->runCommandsLockedInterruptible();
                if (status == WOULD_BLOCK) {
                    return 1;
                }
            }

            notify = status != DEAD_OBJECT || !connection->monitor;
            if (notify) {
                ALOGE("channel '%s' ~ Failed to receive finished signal.  status=%d",
                        connection->getInputChannelName().c_str(), status);
            }
        }

        // Unregister the channel.
        d->unregisterInputChannelLocked(connection->inputChannel, notify);
        return 0; // remove the callback
    } // release lock
}
3.8 InputDispatcher::onDispatchCycleFinishedLocked

onDispatchCycleFinishedLocked里没有做相关处理,最终实现为InputDispatcher::doDispatchCycleFinishedLockedInterruptible,我们来分析doDispatchCycleFinishedLockedInterruptible函数,将DispatchEntry从waitQueue队列中移除事件,将DispatchEntry相关对象析构, 继续派发下一个事件

void InputDispatcher::onDispatchCycleFinishedLocked(
        nsecs_t currentTime, const sp<Connection>& connection, uint32_t seq, bool handled) {
    CommandEntry* commandEntry = postCommandLocked(
            & InputDispatcher::doDispatchCycleFinishedLockedInterruptible);
    commandEntry->connection = connection;
    commandEntry->eventTime = currentTime;
    commandEntry->seq = seq;
    commandEntry->handled = handled;
}
3.9 InputDispatcher::doDispatchCycleFinishedLockedInterruptible
void InputDispatcher::doDispatchCycleFinishedLockedInterruptible(
        CommandEntry* commandEntry) {
    // Handle post-event policy actions.
    DispatchEntry* dispatchEntry = connection->findWaitQueueEntry(seq);
    if (dispatchEntry) {
      
        // Dequeue the event and start the next cycle.
        // Note that because the lock might have been released, it is possible that the
        // contents of the wait queue to have been drained, so we need to double-check
        // a few things.
        if (dispatchEntry == connection->findWaitQueueEntry(seq)) {
            // step1, 从waitQueue队列中移除事件
            connection->waitQueue.dequeue(dispatchEntry);
            traceWaitQueueLength(connection);
            if (restartEvent && connection->status == Connection::STATUS_NORMAL) {
                // step2, 如果当前事件需要重新派发,则继续派发
                connection->outboundQueue.enqueueAtHead(dispatchEntry);
                traceOutboundQueueLength(connection);
            } else {
                // step3, 释放事件相关对象
                releaseDispatchEntry(dispatchEntry);
            }
        }

        // step4, 派发下一个事件
        startDispatchCycleLocked(now(), connection);
    }
}
3.10 InputDispatcher发送事件流程:
dispatchOnce
    dispatchOnceInnerLocked
        dispatchKeyLocked
            doInterceptKeyBeforeDispatchingLockedInterruptible
                dispatchEventLocked
                    prepareDispatchCycleLocked
                        enqueueDispatchEntriesLocked
                            startDispatchCycleLocked
                                connection->inputPublisher.publishKeyEvent
3.11 InputDispatcher接收事件处理完成流程:
handleReceiveCallback
    connection->inputPublisher.receiveFinishedSignal(&seq, &handled);
        finishDispatchCycleLocked
            onDispatchCycleFinishedLocked
                doDispatchCycleFinishedLockedInterruptible
                    connection->waitQueue.dequeue(dispatchEntry);
                        releaseDispatchEntryLocked(dispatchEntry);

4 Activity和IMS之间是如何建立连接的

WindowManagerService是Android中的窗口服务的,负责窗口的添加删除,Activity的添加会调用WMS中的addWindow函数。addWindow函数非常复杂,我们只分析和输入相关连接的建立,InputChannel.openInputChannelPair会创建一个双向的socket, 返回两个InputChannel,使Activity和IMS之间建立联系,然后将窗口相关的信息更新到IMS中,为InputDispatcher正确派发事件到ViewRootImpl提供保障。

public int addWindow(Session session, IWindow client, int seq,
            WindowManager.LayoutParams attrs, int viewVisibility, int displayId,
            Rect outContentInsets, InputChannel outInputChannel) {
            
    if (outInputChannel != null && (attrs.inputFeatures
            & WindowManager.LayoutParams.INPUT_FEATURE_NO_INPUT_CHANNEL) == 0) {
        String name = win.makeInputChannelName();
        // step1, 创建输入通道
        InputChannel[] inputChannels = InputChannel.openInputChannelPair(name);
        win.setInputChannel(inputChannels[0]);
        // step2, 将inputChannels[1]传给Activity
        inputChannels[1].transferTo(outInputChannel);
        // step3, 将将inputChannels[0]传给IMS
        mInputManager.registerInputChannel(win.mInputChannel, win.mInputWindowHandle);
    }

    // step4, 更新IMS中的窗口
    mInputMonitor.updateInputWindowsLw(false /*force*/);

}
4.1 InputChannel::openInputChannelPair
status_t InputChannel::openInputChannelPair(const String8& name,
        sp<InputChannel>& outServerChannel, sp<InputChannel>& outClientChannel) {
    int sockets[2];
    // 创建socketpair
    if (socketpair(AF_UNIX, SOCK_SEQPACKET, 0, sockets)) {
        status_t result = -errno;
        ALOGE("channel '%s' ~ Could not create socket pair.  errno=%d",
                name.string(), errno);
        outServerChannel.clear();
        outClientChannel.clear();
        return result;
    }

    int bufferSize = SOCKET_BUFFER_SIZE;
    setsockopt(sockets[0], SOL_SOCKET, SO_SNDBUF, &bufferSize, sizeof(bufferSize));
    setsockopt(sockets[0], SOL_SOCKET, SO_RCVBUF, &bufferSize, sizeof(bufferSize));
    setsockopt(sockets[1], SOL_SOCKET, SO_SNDBUF, &bufferSize, sizeof(bufferSize));
    setsockopt(sockets[1], SOL_SOCKET, SO_RCVBUF, &bufferSize, sizeof(bufferSize));

    String8 serverChannelName = name;
    serverChannelName.append(" (server)");
    outServerChannel = new InputChannel(serverChannelName, sockets[0]);

    String8 clientChannelName = name;
    clientChannelName.append(" (client)");
    outClientChannel = new InputChannel(clientChannelName, sockets[1]);
    return OK;
}
4.2 com_android_server_input_InputManagerService.cpp

mInputManager.registerInputChannel()函数最终实现为native层中的InputDispatcher::registerInputChannel,创建对应的连接对象,将socket添加到loop中监听,当收到消息,回调InputDispatcher::handleReceiveCallback来处理按键事件的收尾工作

status_t InputDispatcher::registerInputChannel(const sp<InputChannel>& inputChannel,
        int32_t displayId) {
    { // acquire lock
        std::scoped_lock _l(mLock);

        // step1, 创建连接通道
        sp<Connection> connection = new Connection(inputChannel, false /*monitor*/);

        int fd = inputChannel->getFd();
        mConnectionsByFd.add(fd, connection);
        mInputChannelsByToken[inputChannel->getToken()] = inputChannel;
        // step2, 建立回调机制
        mLooper->addFd(fd, 0, ALOOPER_EVENT_INPUT, handleReceiveCallback, this);
    } // release lock

    // Wake the looper because some connections have changed.
    mLooper->wake();
    return OK;
}

5 总结

Android Activity输入事件分发机制没有分析,请看我的另一篇文章
Android Activity输入事件分发机制

5.1 整体框架图

在这里插入图片描述

5.2 交互过程

在这里插入图片描述

  • 2
    点赞
  • 3
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值