Android Input系统的启动以及Input场景下的ANR


为了分析Input场景下ANR发生的原因,特意找了对Input系统全面介绍的一篇文章,如果系统对于Input Event超过预定时间(5s)没有响应,则会弹出ANR提示用户继续等待或者选择FC。通过下面文章对Input事件传递流程的分析,在InputDispatcher.cpp里面会对持有分发锁有一个超时时间(3s),在WMS中才是对事件真正开始计时。


  • InputDispatching Timeout: 输入事件分发超时5s,包括按键和触摸事件。
原文地址:http://gityuan.com/2016/07/02/android-anr/

一. 概述

先简单总结和回顾以下前几篇文章的内容:

  • Input系统—InputReader线程:通过EventHub从/dev/input节点获取事件,转换成EventEntry事件加入到InputDispatcher的mInboundQueue。
  • Input系统—InputDispatcher线程:从mInboundQueue队列取出事件,转换成DispatchEntry事件加入到connection的outboundQueue队列。再然后开始处理分发事件,取出outbound队列,放入waitQueue.
  • Input系统—UI线程:创建socket pair,分别位于”InputDispatcher”线程和focused窗口所在进程的UI主线程,可相互通信。
    • UI主线程:通过setFdEvents(), 监听socket客户端,收到消息后回调NativeInputEventReceiver();【见小节2.1】
    • “InputDispatcher”线程: 通过IMS.registerInputChannel(),监听socket服务端,收到消息后回调handleReceiveCallback;【见小节3.1】

接下来,以按键事件为例,说一说一次事件处理过程是如何完成。按键事件经过InputReader,再到InputDispatcher的startDispatchCycleLocked()过程会调用publishKeyEvent(),从该方法说起。

二. InputDispatcher线程

2.1 InputPublisher.publishKeyEvent

[-> InputTransport.cpp]

status_t InputPublisher::publishKeyEvent(...) {
    if (!seq) {
        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;
    //通过InputChannel来发送消息
    return mChannel->sendMessage(&msg);
}

2.2 InputChannel.sendMessage

[-> InputTransport.cpp]

status_t InputChannel::sendMessage(const InputMessage* msg) {
    size_t msgLength = msg->size();
    ssize_t nWrite;
    do {
        //向目标mFd写入消息,采用异步非阻塞方式
        nWrite = ::send(mFd, msg, msgLength, MSG_DONTWAIT | MSG_NOSIGNAL);
    } while (nWrite == -1 && errno == EINTR);

    if (nWrite < 0) {
        int error = errno;
        if (error == EAGAIN || error == EWOULDBLOCK) {
            return WOULD_BLOCK;
        }
        if (error == EPIPE || error == ENOTCONN || error == ECONNREFUSED || error == ECONNRESET) {
            return DEAD_OBJECT;
        }
        return -error;
    }

    if (size_t(nWrite) != msgLength) {
        return DEAD_OBJECT;
    }

    return OK;
}

Input系统—UI线程讲解了会创建socket pair,用于两个进程的线程间相互通信。当mFd写入消息后,此时会唤醒处于epoll_wait状态的应用进程的UI线程,见下文。

另外,当写入失败,则返回值为WOULD_BLOCK或者DEAD_OBJECT。

三. UI主线程

当收到消息的处理过程,Android消息机制在获取下一条消息的时候,会调用lnativePollOnce(),最终进入到Looper::pollInner()过程,如下:

3.1 Looper::pollInner

int Looper::pollInner(int timeoutMillis) {
    ...
    int result = POLL_WAKE;
    mResponses.clear();
    mResponseIndex = 0;
    mPolling = true; //即将处于idle状态
    struct epoll_event eventItems[EPOLL_MAX_EVENTS]; //fd最大个数为16

    //等待事件发生或者超时,在nativeWake()方法,向管道写端写入字符;
    int eventCount = epoll_wait(mEpollFd, eventItems, EPOLL_MAX_EVENTS, timeoutMillis);
    mPolling = false; //不再处于idle状态

    mLock.lock();  //请求锁
    ...

    //循环遍历,处理所有的事件
    for (int i = 0; i < eventCount; i++) {
        int fd = eventItems[i].data.fd;
        uint32_t epollEvents = eventItems[i].events;
        if (fd == mWakeEventFd) {
            if (epollEvents & EPOLLIN) {
                awoken(); //已唤醒则读取并清空管道数据
            }
        } else {
            ssize_t requestIndex = mRequests.indexOfKey(fd);
            if (requestIndex >= 0) {
                int events = 0;
                if (epollEvents & EPOLLIN) events |= EVENT_INPUT;
                if (epollEvents & EPOLLOUT) events |= EVENT_OUTPUT;
                if (epollEvents & EPOLLERR) events |= EVENT_ERROR;
                if (epollEvents & EPOLLHUP) events |= EVENT_HANGUP;

                //处理request,生成对应的reponse对象,push到mResponses数组
                pushResponse(events, mRequests.valueAt(requestIndex));
            }
        }
    }
Done: ;
    //再处理Native的Message,调用相应回调方法
    while (mMessageEnvelopes.size() != 0) {
        nsecs_t now = systemTime(SYSTEM_TIME_MONOTONIC);
        //取出消息
        const MessageEnvelope& messageEnvelope = mMessageEnvelopes.itemAt(0);
        if (messageEnvelope.uptime <= now) {
            sp<MessageHandler> handler = messageEnvelope.handler;
            Message message = messageEnvelope.message;
            mMessageEnvelopes.removeAt(0); //移除该消息
            mLock.unlock();
            handler->handleMessage(message);  // 处理消息事件
        }
        mLock.lock();
        ...
    }
    mLock.unlock(); //释放锁

    //处理带有Callback()方法的Response事件,执行Reponse相应的回调方法
    for (size_t i = 0; i < mResponses.size(); i++) {
        Response& response = mResponses.editItemAt(i);
        if (response.request.ident == POLL_CALLBACK) {
            int fd = response.request.fd;
            int events = response.events;
            void* data = response.request.data;
            // 处理请求的回调方法【见小节3.2】
            int callbackResult = response.request.callback->handleEvent(fd, events, data);
            if (callbackResult == 0) {
                removeFd(fd, response.request.seq); //移除fd
            }
            response.request.callback.clear(); //清除reponse引用的回调方法
            result = POLL_CALLBACK;  // 发生回调
        }
    }
    return result;
}

此处response.request.callback是指NativeInputEventReceiver,接下来便是执行NativeInputEventReceiver.handleEvent();

3.2 handleEvent

[-> android_view_InputEventReceiver.cpp]

int NativeInputEventReceiver::handleEvent(int receiveFd, int events, void* data) {
    if (events & (ALOOPER_EVENT_ERROR | ALOOPER_EVENT_HANGUP)) {
        return 0;  //移除窗口或者IME对话框, 则移除该事件
    }

    if (events & ALOOPER_EVENT_INPUT) {
        JNIEnv* env = AndroidRuntime::getJNIEnv();
        //【见小节3.3】
        status_t status = consumeEvents(env, false /*consumeBatches*/, -1, NULL);
        mMessageQueue->raiseAndClearException(env, "handleReceiveCallback");
        return status == OK || status == NO_MEMORY ? 1 : 0;
    }

    if (events & ALOOPER_EVENT_OUTPUT) {
        for (size_t i = 0; i < mFinishQueue.size(); i++) {
            const Finish& finish = mFinishQueue.itemAt(i);
            //【见小节3.4】
            status_t status = mInputConsumer.sendFinishedSignal(finish.seq, finish.handled);
            if (status) {
                mFinishQueue.removeItemsAt(0, i);

                if (status == WOULD_BLOCK) {
                    return 1; //保留callback,稍后重试
                }

                if (status != DEAD_OBJECT) {
                    JNIEnv* env = AndroidRuntime::getJNIEnv();
                    String8 message;
                    message.appendFormat("Failed to finish input event.  status=%d", status);
                    jniThrowRuntimeException(env, message.string());
                    mMessageQueue->raiseAndClearException(env, "finishInputEvent");
                }
                return 0; //移除callback
            }
        }
        mFinishQueue.clear();
        setFdEvents(ALOOPER_EVENT_INPUT);
        return 1;
    }
    return 1;
}

UI线程收到Key事件后,开始处理该事件。

3.3 NativeInputEventReceiver.consumeEvents

[-> android_view_InputEventReceiver.cpp]

status_t NativeInputEventReceiver::consumeEvents(JNIEnv* env,
        bool consumeBatches, nsecs_t frameTime, bool* outConsumedBatch) {
    ...

    ScopedLocalRef<jobject> receiverObj(env, NULL);
    bool skipCallbacks = false;
    for (;;) {
        uint32_t seq;
        InputEvent* inputEvent;
        //【见小节3.3.1】
        status_t status = mInputConsumer.consume(&mInputEventFactory,
                consumeBatches, frameTime, &seq, &inputEvent);
        if (status) {
            if (status == WOULD_BLOCK) {
                ...
                return OK; //消费完成
            }
            return status; //消失失败
        }

        if (!skipCallbacks) {
            if (!receiverObj.get()) {
                receiverObj.reset(jniGetReferent(env, mReceiverWeakGlobal));
                if (!receiverObj.get()) {
                    return DEAD_OBJECT;
                }
            }

            jobject inputEventObj;
            switch (inputEvent->getType()) {
                case AINPUT_EVENT_TYPE_KEY:
                    //由Native的inputEvent来生成Java层的事件
                    inputEventObj = android_view_KeyEvent_fromNative(env,
                            static_cast<KeyEvent*>(inputEvent));
                    break;
                ...
            }

            if (inputEventObj) {
                //执行Java层的InputEventReceiver.dispachInputEvent【见小节3.3.3】
                env->CallVoidMethod(receiverObj.get(),
                        gInputEventReceiverClassInfo.dispatchInputEvent, seq, inputEventObj);
                if (env->ExceptionCheck()) {
                    skipCallbacks = true; //分发过程发生异常
                }
                env->DeleteLocalRef(inputEventObj);
            } else {
                skipCallbacks = true;
            }
        }

        if (skipCallbacks) {
            //发生异常,则直接向InputDispatcher线程发送完成信号。
            mInputConsumer.sendFinishedSignal(seq, false);
        }
    }
}
3.3.1 InputConsumer.consume

[->InputTransport.cpp ::InputConsumer]

status_t InputConsumer::consume(InputEventFactoryInterface* factory,
        bool consumeBatches, nsecs_t frameTime, uint32_t* outSeq, InputEvent** outEvent) {

    *outSeq = 0;
    *outEvent = NULL;

    //循环遍历所有的Event
    while (!*outEvent) {
        if (mMsgDeferred) {
            mMsgDeferred = false; //上一次没有处理的消息
        } else {
            //收到新消息【见小节3.3.2】
            status_t result = mChannel->receiveMessage(&mMsg);
            if (result) {
                if (consumeBatches || result != WOULD_BLOCK) {
                    result = consumeBatch(factory, frameTime, outSeq, outEvent);
                    if (*outEvent) {
                        break;
                    }
                }
                return result;
            }
        }

        switch (mMsg.header.type) {
          case InputMessage::TYPE_KEY: {
              //从mKeyEventPool池中取出KeyEvent
              KeyEvent* keyEvent = factory->createKeyEvent();
              if (!keyEvent) return NO_MEMORY;

              //将msg封装成KeyEvent
              initializeKeyEvent(keyEvent, &mMsg);
              *outSeq = mMsg.body.key.seq;
              *outEvent = keyEvent;
              break;
          }
          ...
        }
    }
    return OK;
}
3.3.2 InputChannel.receiveMessage

[-> InputTransport.cpp]

status_t InputChannel::receiveMessage(InputMessage* msg) {
    ssize_t nRead;
    do {
        //读取InputDispatcher发送过来的消息
        nRead = ::recv(mFd, msg, sizeof(InputMessage), MSG_DONTWAIT);
    } while (nRead == -1 && errno == EINTR);

    if (nRead < 0) {
        int error = errno;
        if (error == EAGAIN || error == EWOULDBLOCK) {
            return WOULD_BLOCK;
        }
        if (error == EPIPE || error == ENOTCONN || error == ECONNREFUSED) {
            return DEAD_OBJECT;
        }
        return -error;
    }

    if (nRead == 0) {
        return DEAD_OBJECT;
    }

    if (!msg->isValid(nRead)) {
        return BAD_VALUE;
    }

    return OK;
}
3.3.3 InputEventReceiver.dispachInputEvent

[-> InputEventReceiver.java]

private void dispatchInputEvent(int seq, InputEvent event) {
    mSeqMap.put(event.getSequenceNumber(), seq);
    onInputEvent(event); //[见小节3.3.4]
}
3.3.4 onInputEvent

[-> ViewRootImpl.java ::WindowInputEventReceiver]

final class WindowInputEventReceiver extends InputEventReceiver {
    public void onInputEvent(InputEvent event) {
       enqueueInputEvent(event, this, 0, true); //【见小节3.3.5】
    }
    ...
}
3.3.5 enqueueInputEvent

[-> ViewRootImpl.java]

void enqueueInputEvent(InputEvent event,
        InputEventReceiver receiver, int flags, boolean processImmediately) {
    adjustInputEventForCompatibility(event);
    QueuedInputEvent q = obtainQueuedInputEvent(event, receiver, flags);

    QueuedInputEvent last = mPendingInputEventTail;
    if (last == null) {
        mPendingInputEventHead = q;
        mPendingInputEventTail = q;
    } else {
        last.mNext = q;
        mPendingInputEventTail = q;
    }
    mPendingInputEventCount += 1;

    if (processImmediately) {
        doProcessInputEvents(); //【见小节3.3.6】
    } else {
        scheduleProcessInputEvents();
    }
}
3.3.6 doProcessInputEvents

[-> ViewRootImpl.java]

void doProcessInputEvents() {
    while (mPendingInputEventHead != null) {
        QueuedInputEvent q = mPendingInputEventHead;
        mPendingInputEventHead = q.mNext;
        if (mPendingInputEventHead == null) {
            mPendingInputEventTail = null;
        }
        q.mNext = null;

        mPendingInputEventCount -= 1;

        long eventTime = q.mEvent.getEventTimeNano();
        long oldestEventTime = eventTime;
        ...
        mChoreographer.mFrameInfo.updateInputEventTime(eventTime, oldestEventTime);
        //[见小节3.3.7]
        deliverInputEvent(q);
    }

    if (mProcessInputEventsScheduled) {
        mProcessInputEventsScheduled = false;
        mHandler.removeMessages(MSG_PROCESS_INPUT_EVENTS);
    }
}
3.3.7 事件分发

[-> ViewRootImpl.java]

private void deliverInputEvent(QueuedInputEvent q) {
     if (mInputEventConsistencyVerifier != null) {
         mInputEventConsistencyVerifier.onInputEvent(q.mEvent, 0);
     }

     InputStage stage;
     if (q.shouldSendToSynthesizer()) {
         stage = mSyntheticInputStage;
     } else {
         stage = q.shouldSkipIme() ? mFirstPostImeInputStage : mFirstInputStage;
     }

     if (stage != null) {
         stage.deliver(q);
     } else {
         finishInputEvent(q); //[见小节3.4]
     }
 }

经过一系列的InputStage调用, 最终会分发到真正需要处理该时间的窗口. 当处理完后会调用finishInputEvent(), 见小节3.4

3.4 finishInputEvent

[-> ViewRootImpl.java]

 private void finishInputEvent(QueuedInputEvent q) {

    if (q.mReceiver != null) {
        boolean handled = (q.mFlags & QueuedInputEvent.FLAG_FINISHED_HANDLED) != 0;
        //[见小节3.4.1]
        q.mReceiver.finishInputEvent(q.mEvent, handled);
    } else {
        q.mEvent.recycleIfNeededAfterDispatch();
    }
    recycleQueuedInputEvent(q);
}
3.4.1 mReceiver.finishInputEvent
public final void finishInputEvent(InputEvent event, boolean handled) {
    if (mReceiverPtr == 0) {
        ...
    } else {
        int index = mSeqMap.indexOfKey(event.getSequenceNumber());
        if (index < 0) {
            ...
        } else {
            int seq = mSeqMap.valueAt(index);
            mSeqMap.removeAt(index);
            //经过层层调用,见[小节3.5]
            nativeFinishInputEvent(mReceiverPtr, seq, handled);
        }
    }
    event.recycleIfNeededAfterDispatch();
}

3.5 sendFinishedSignal

[-> InputTransport.cpp ::InputConsumer]

status_t InputConsumer::sendFinishedSignal(uint32_t seq, bool handled) {
    ...

    size_t seqChainCount = mSeqChains.size();
    if (seqChainCount) {
        uint32_t currentSeq = seq;
        uint32_t chainSeqs[seqChainCount];
        size_t chainIndex = 0;
        for (size_t i = seqChainCount; i-- > 0; ) {
             const SeqChain& seqChain = mSeqChains.itemAt(i);
             if (seqChain.seq == currentSeq) {
                 currentSeq = seqChain.chain;
                 chainSeqs[chainIndex++] = currentSeq;
                 mSeqChains.removeAt(i);
             }
        }
        status_t status = OK;
        while (!status && chainIndex-- > 0) {
            //[见小节3.5.1]
            status = sendUnchainedFinishedSignal(chainSeqs[chainIndex], handled);
        }
        if (status) {
            // An error occurred so at least one signal was not sent, reconstruct the chain.
            do {
                SeqChain seqChain;
                seqChain.seq = chainIndex != 0 ? chainSeqs[chainIndex - 1] : seq;
                seqChain.chain = chainSeqs[chainIndex];
                mSeqChains.push(seqChain);
            } while (chainIndex-- > 0);
            return status;
        }
    }

    return sendUnchainedFinishedSignal(seq, handled);
}
3.5.1 sendUnchainedFinishedSignal

[-> InputTransport.cpp ::InputConsumer]

status_t InputConsumer::sendUnchainedFinishedSignal(uint32_t seq, bool handled) {
    InputMessage msg;
    msg.header.type = InputMessage::TYPE_FINISHED;
    msg.body.finished.seq = seq;
    msg.body.finished.handled = handled;
    return mChannel->sendMessage(&msg);
}

通过InputChannel->sendMessage,将TYPE_FINISHED类型的消息,发送回InputDispatcher线程。

四. InputDispatcher线程

4.1 Looper::pollInner

int Looper::pollInner(int timeoutMillis) {

    int eventCount = epoll_wait(mEpollFd, eventItems, EPOLL_MAX_EVENTS, timeoutMillis);
    ...

Done:
    ...
    for (size_t i = 0; i < mResponses.size(); i++) {
        Response& response = mResponses.editItemAt(i);
        if (response.request.ident == POLL_CALLBACK) {
            int fd = response.request.fd;
            int events = response.events;
            void* data = response.request.data;
            // 处理请求的回调方法【见小节4.2】
            int callbackResult = response.request.callback->handleEvent(fd, events, data);
            ...
        }
    }
    return result;
}

此处response.request.callback是指SimpleLooperCallback。接下来调用SimpleLooperCallback.handleEvent(). 执行后的返回值callbackResult=0则移除该fd,否则稍后重新尝试。

4.2 handleEvent

[-> Looper.cpp ::SimpleLooperCallback]

SimpleLooperCallback::SimpleLooperCallback(Looper_callbackFunc callback) :
        mCallback(callback) {
}

int SimpleLooperCallback::handleEvent(int fd, int events, void* data) {
    //handleReceiveCallback()【见小节4.3】
    return mCallback(fd, events, data);
}

IMS.registerInputChannel()过程,会调用Looper.addFd()完成的赋值操作,mCallback等于handleReceiveCallback()方法。

4.3 handleReceiveCallback

[-> InputDispatcher]

int InputDispatcher::handleReceiveCallback(int fd, int events, void* data) {
    InputDispatcher* d = static_cast<InputDispatcher*>(data);
    {
        AutoMutex _l(d->mLock);
        ssize_t connectionIndex = d->mConnectionsByFd.indexOfKey(fd);

        bool notify;
        sp<Connection> connection = d->mConnectionsByFd.valueAt(connectionIndex);
        if (!(events & (ALOOPER_EVENT_ERROR | ALOOPER_EVENT_HANGUP))) {
            ...
            nsecs_t currentTime = now();
            bool gotOne = false;
            status_t status;
            for (;;) {
                uint32_t seq;
                bool handled;
                //【见小节4.4】
                status = connection->inputPublisher.receiveFinishedSignal(&seq, &handled);
                if (status) {
                    break;
                }
                //【见小节4.5】
                d->finishDispatchCycleLocked(currentTime, connection, seq, handled);
                gotOne = true;
            }
            if (gotOne) {
                d->runCommandsLockedInterruptible(); //执行命令【见小节4.6】
                if (status == WOULD_BLOCK) {
                    return 1;
                }
            }
            notify = status != DEAD_OBJECT || !connection->monitor;
        } else {
            ...
             //input channel被关闭或者发生错误
        }

        //取消注册channel
        d->unregisterInputChannelLocked(connection->inputChannel, notify);
        return 0;
    }
}

4.4 InputPublisher.receiveFinishedSignal

[-> InputTransport.cpp]

status_t InputPublisher::receiveFinishedSignal(uint32_t* outSeq, bool* outHandled) {

    InputMessage msg;
    //接收消息
    status_t result = mChannel->receiveMessage(&msg);
    if (result) {
        *outSeq = 0;
        *outHandled = false;
        return result;
    }
    if (msg.header.type != InputMessage::TYPE_FINISHED) {
        return UNKNOWN_ERROR; //发生错误
    }
    *outSeq = msg.body.finished.seq;
    *outHandled = msg.body.finished.handled;
    return OK;
}

4.5 finishDispatchCycleLocked

[-> InputDispatcher.cpp]

void InputDispatcher::finishDispatchCycleLocked(nsecs_t currentTime,
        const sp<Connection>& connection, uint32_t seq, bool handled) {

    connection->inputPublisherBlocked = false;

    if (connection->status == Connection::STATUS_BROKEN
            || connection->status == Connection::STATUS_ZOMBIE) {
        return;
    }

    //通知系统准备启动下一次分发流程【见小节4.5.1】
    onDispatchCycleFinishedLocked(currentTime, connection, seq, handled);
}
4.5.1 onDispatchCycleFinishedLocked

[-> InputDispatcher.cpp]

void InputDispatcher::onDispatchCycleFinishedLocked(
        nsecs_t currentTime, const sp<Connection>& connection, uint32_t seq, bool handled) {
    //向mCommandQueue添加命令
    CommandEntry* commandEntry = postCommandLocked(
            & InputDispatcher::doDispatchCycleFinishedLockedInterruptible);
    commandEntry->connection = connection;
    commandEntry->eventTime = currentTime;
    commandEntry->seq = seq;
    commandEntry->handled = handled;
}

4.6 runCommandsLockedInterruptible

[-> InputDispatcher.cpp]

bool InputDispatcher::runCommandsLockedInterruptible() {
    if (mCommandQueue.isEmpty()) {
        return false;
    }

    do {
        //从mCommandQueue队列的头部取出第一个元素【见小节4.6.1】
        CommandEntry* commandEntry = mCommandQueue.dequeueAtHead();

        Command command = commandEntry->command;
        //此处调用的命令隐式地包含'LockedInterruptible'
        (this->*command)(commandEntry);

        commandEntry->connection.clear();
        delete commandEntry;
    } while (! mCommandQueue.isEmpty());
    return true;
}

由【小节4.5】,可以队列中的元素至少有doDispatchCycleFinishedLockedInterruptible。

4.6.1 doDispatchCycleFinishedLockedInterruptible

[-> InputDispatcher.cpp]

void InputDispatcher::doDispatchCycleFinishedLockedInterruptible(
        CommandEntry* commandEntry) {
    sp<Connection> connection = commandEntry->connection;
    nsecs_t finishTime = commandEntry->eventTime;
    uint32_t seq = commandEntry->seq;
    bool handled = commandEntry->handled;

    //获取分发事件
    DispatchEntry* dispatchEntry = connection->findWaitQueueEntry(seq);
    if (dispatchEntry) {
        nsecs_t eventDuration = finishTime - dispatchEntry->deliveryTime;
        //打印出所有分发时间超过2s的事件
        if (eventDuration > SLOW_EVENT_PROCESSING_WARNING_TIMEOUT) {
            String8 msg;
            msg.appendFormat("Window '%s' spent %0.1fms processing the last input event: ",
                    connection->getWindowName(), eventDuration * 0.000001f);
            dispatchEntry->eventEntry->appendDescription(msg);
            ALOGI("%s", msg.string());
        }

        bool restartEvent;
        if (dispatchEntry->eventEntry->type == EventEntry::TYPE_KEY) {
            KeyEntry* keyEntry = static_cast<KeyEntry*>(dispatchEntry->eventEntry);
            restartEvent = afterKeyEventLockedInterruptible(connection,
                    dispatchEntry, keyEntry, handled);
        } else if (dispatchEntry->eventEntry->type == EventEntry::TYPE_MOTION) {
            ...
        } else {
            ...
        }

        if (dispatchEntry == connection->findWaitQueueEntry(seq)) {
            //将dispatchEntry事件从等待队列(waitQueue)中移除
            connection->waitQueue.dequeue(dispatchEntry);
            if (restartEvent && connection->status == Connection::STATUS_NORMAL) {
                connection->outboundQueue.enqueueAtHead(dispatchEntry);
            } else {
                releaseDispatchEntryLocked(dispatchEntry);
            }
        }

        //启动下一个事件处理循环。
        startDispatchCycleLocked(now(), connection);
    }
}

该方法主要功能:

  • 打印出所有分发时间超过2s的事件;
  • 将dispatchEntry事件从等待队列(waitQueue)中移除;
  • 启动下一个事件处理循环。

五. 总结

5.1 整体框架图

input_summary

5.2 交互过程

用一张图来总结交互过程,主要是通过一对socket方式来通信。 当input时间分发到app端, 那么便进入来了InputEventReceiver.dispatchInputEvent()过程.

input_socket

图解:

  1. InputDispatcher线程调用InputPublisher的publishKeyEvent向UI主线程发送input事件;
  2. UI主线程接收到该事件后,调用InputConsumer的consumeEvents来处理该事件, 一路执行到ViewRootImpl.deliverInputEvent()方法;
  3. UI主线程经过一系列的InputStage来处理, 当事件分发完成,则会执行finishInputEvent()方法.再进一步调用InputConsumer::sendFinishedSignal 告知InputDispatcher线程该时事件已处理完成.
  4. InputDispatcher线程收到该事件后, 执行InputDispatcher::handleReceiveCallback();最终会调用doDispatchCycleFinishedLockedInterruptible()方法 ,将dispatchEntry事件从等待队列(waitQueue)中移除.

基于Android 6.0源码, 分析InputManagerService的启动过程

frameworks/native/services/inputflinger/
  - InputDispatcher.cpp
  - InputReader.cpp
  - InputManager.cpp
  - EventHub.cpp
  - InputListener.cpp

frameworks/native/libs/input/
  - InputTransport.cpp
  - Input.cpp
  - InputDevice.cpp
  - Keyboard.cpp
  - KeyCharacterMap.cpp
  - IInputFlinger.cpp

frameworks/base/services/core/
  - java/com/android/server/input/InputManagerService.java
  - jni/com_android_server_input_InputManagerService.cpp

一. 概述

当用户触摸屏幕或者按键操作,首次触发的是硬件驱动,驱动收到事件后,将该相应事件写入到输入设备节点, 这便产生了最原生态的内核事件。接着,输入系统取出原生态的事件,经过层层封装后成为KeyEvent或者MotionEvent ;最后,交付给相应的目标窗口(Window)来消费该输入事件。可见,输入系统在整个过程起到承上启下的衔接作用。

Input模块的主要组成:

  • Native层的InputReader负责从EventHub取出事件并处理,再交给InputDispatcher;
  • Native层的InputDispatcher接收来自InputReader的输入事件,并记录WMS的窗口信息,用于派发事件到合适的窗口;
  • Java层的InputManagerService跟WMS交互,WMS记录所有窗口信息,并同步更新到IMS,为InputDispatcher正确派发事件到ViewRootImpl提供保障;

Input相关的动态库:

  • libinputflinger.so:frameworks/native/services/inputflinger/
  • libinputservice.so:frameworks/base/libs/input/
  • libinput.so: frameworks/native/libs/input/

1.1 整体框架类图

InputManagerService作为system_server中的重要服务,继承于IInputManager.Stub, 作为Binder服务端,那么Client位于InputManager的内部通过IInputManager.Stub.asInterface() 获取Binder代理端,C/S两端通信的协议是由IInputManager.aidl来定义的。

input_binder

Input模块所涉及的重要类的关系如下:

input_class

图解:

  • InputManagerService位于Java层的InputManagerService.java文件;
    • 其成员mPtr指向Native层的NativeInputManager对象;
  • NativeInputManager位于Native层的com_android_server_input_InputManagerService.cpp文件;
    • 其成员mServiceObj指向Java层的IMS对象;
    • 其成员mLooper是指“android.display”线程的Looper;
  • InputManager位于libinputflinger中的InputManager.cpp文件;
    • InputDispatcher和InputReader的成员变量mPolicy都是指NativeInputManager对象;
    • InputReader的成员mQueuedListener,数据类型为QueuedInputListener;通过其内部成员变量mInnerListener指向InputDispatcher对象; 这便是InputReader跟InputDispatcher交互的中间枢纽。

1.2 启动调用栈

IMS服务是伴随着system_server进程的启动而启动,整个调用过程:

InputManagerService(初始化)
    nativeInit
        NativeInputManager
            EventHub
            InputManager
                InputDispatcher
                    Looper
                InputReader
                    QueuedInputListener
                InputReaderThread
                InputDispatcherThread
IMS.start(启动)
    nativeStart
        InputManager.start
            InputReaderThread->run
            InputDispatcherThread->run

整个过程首先创建如下对象:NativeInputManager,EventHub,InputManager, InputDispatcher,InputReader,InputReaderThread,InputDispatcherThread。 接着便是启动两个工作线程InputReader,InputDispatcher

二. 启动过程

private void startOtherServices() {
    //初始化IMS对象【见小节2.1】
    inputManager = new InputManagerService(context);
    ServiceManager.addService(Context.INPUT_SERVICE, inputManager);
    ...
    //将InputMonitor对象保持到IMS对象
    inputManager.setWindowManagerCallbacks(wm.getInputMonitor());
    //[见小节2.9]
    inputManager.start();
}

2.1 InputManagerService

[-> InputManagerService.java]

public InputManagerService(Context context) {
     this.mContext = context;
     // 运行在线程"android.display"
     this.mHandler = new InputManagerHandler(DisplayThread.get().getLooper());
     ...

     //初始化native对象【见小节2.2】
     mPtr = nativeInit(this, mContext, mHandler.getLooper().getQueue());
     LocalServices.addService(InputManagerInternal.class, new LocalService());
 }
2.2 nativeInit

[-> com_android_server_input_InputManagerService.cpp]

static jlong nativeInit(JNIEnv* env, jclass /* clazz */,
        jobject serviceObj, jobject contextObj, jobject messageQueueObj) {
    //获取native消息队列
    sp<MessageQueue> messageQueue = android_os_MessageQueue_getMessageQueue(env, messageQueueObj);
    ...
    //创建Native的InputManager【见小节2.3】
    NativeInputManager* im = new NativeInputManager(contextObj, serviceObj,
            messageQueue->getLooper());
    im->incStrong(0);
    return reinterpret_cast<jlong>(im); //返回Native对象的指针
}

2.3 NativeInputManager

[-> com_android_server_input_InputManagerService.cpp]

NativeInputManager::NativeInputManager(jobject contextObj,
        jobject serviceObj, const sp<Looper>& looper) :
        mLooper(looper), mInteractive(true) {
    JNIEnv* env = jniEnv();
    mContextObj = env->NewGlobalRef(contextObj); //上层IMS的context
    mServiceObj = env->NewGlobalRef(serviceObj); //上层IMS对象
    ...
    sp<EventHub> eventHub = new EventHub(); // 创建EventHub对象【见小节2.4】
    mInputManager = new InputManager(eventHub, this, this); // 创建InputManager对象【见小节2.5】
}

此处的mLooper是指“android.display”线程的Looper; libinputservice.so库中PointerController和SpriteController对象都继承于于MessageHandler, 这两个Handler采用的便是该mLooper.

2.4 EventHub

[-> EventHub.cpp]

EventHub::EventHub(void) :
        mBuiltInKeyboardId(NO_BUILT_IN_KEYBOARD), mNextDeviceId(1), mControllerNumbers(),
        mOpeningDevices(0), mClosingDevices(0),
        mNeedToSendFinishedDeviceScan(false),
        mNeedToReopenDevices(false), mNeedToScanDevices(true),
        mPendingEventCount(0), mPendingEventIndex(0), mPendingINotify(false) {
    acquire_wake_lock(PARTIAL_WAKE_LOCK, WAKE_LOCK_ID);
    //创建epoll
    mEpollFd = epoll_create(EPOLL_SIZE_HINT);

    mINotifyFd = inotify_init();
    //此处DEVICE_PATH为"/dev/input",监听该设备路径
    int result = inotify_add_watch(mINotifyFd, DEVICE_PATH, IN_DELETE | IN_CREATE);

    struct epoll_event eventItem;
    memset(&eventItem, 0, sizeof(eventItem));
    eventItem.events = EPOLLIN;
    eventItem.data.u32 = EPOLL_ID_INOTIFY;
    //添加INotify到epoll实例
    result = epoll_ctl(mEpollFd, EPOLL_CTL_ADD, mINotifyFd, &eventItem);

    int wakeFds[2];
    result = pipe(wakeFds); //创建管道

    mWakeReadPipeFd = wakeFds[0];
    mWakeWritePipeFd = wakeFds[1];

    //将pipe的读和写都设置为非阻塞方式
    result = fcntl(mWakeReadPipeFd, F_SETFL, O_NONBLOCK);
    result = fcntl(mWakeWritePipeFd, F_SETFL, O_NONBLOCK);

    eventItem.data.u32 = EPOLL_ID_WAKE;
    //添加管道的读端到epoll实例
    result = epoll_ctl(mEpollFd, EPOLL_CTL_ADD, mWakeReadPipeFd, &eventItem);
    ...
}

该方法主要功能:

  • 初始化INotify(监听”/dev/input”),并添加到epoll实例
  • 创建非阻塞模式的管道,并添加到epoll;

2.5 InputManager

[-> InputManager.cpp]

InputManager::InputManager(
        const sp<EventHubInterface>& eventHub,
        const sp<InputReaderPolicyInterface>& readerPolicy,
        const sp<InputDispatcherPolicyInterface>& dispatcherPolicy) {
    //创建InputDispatcher对象【见小节2.6】
    mDispatcher = new InputDispatcher(dispatcherPolicy);
    //创建InputReader对象【见小节2.7】
    mReader = new InputReader(eventHub, readerPolicy, mDispatcher);
    initialize();//【见小节2.8】
}

InputDispatcher和InputReader的mPolicy成员变量都是指NativeInputManager对象。

2.6 InputDispatcher

[-> InputDispatcher.cpp]

InputDispatcher::InputDispatcher(const sp<InputDispatcherPolicyInterface>& policy) :
    mPolicy(policy),
    mPendingEvent(NULL), mLastDropReason(DROP_REASON_NOT_DROPPED),
    mAppSwitchSawKeyDown(false), mAppSwitchDueTime(LONG_LONG_MAX),
    mNextUnblockedEvent(NULL),
    mDispatchEnabled(false), mDispatchFrozen(false), mInputFilterEnabled(false),
    mInputTargetWaitCause(INPUT_TARGET_WAIT_CAUSE_NONE) {
    //创建Looper对象
    mLooper = new Looper(false);

    mKeyRepeatState.lastKeyEntry = NULL;
    //获取分发超时参数
    policy->getDispatcherConfiguration(&mConfig);
}

该方法主要工作:

  • 创建属于自己线程的Looper对象;
  • 超时参数来自于IMS,参数默认值keyRepeatTimeout = 500,keyRepeatDelay = 50。
2.7 InputReader

[-> InputReader.cpp]

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) {
    // 创建输入监听对象
    mQueuedListener = new QueuedInputListener(listener);
    {
        AutoMutex _l(mLock);
        refreshConfigurationLocked(0);
        updateGlobalMetaStateLocked();
    }
}

此处mQueuedListener的成员变量mInnerListener便是InputDispatcher对象。 前面【小节2.5】InputManager创建完InputDispatcher和InputReader对象, 接下里便是调用initialize初始化。

2.8 initialize

[-> InputManager.cpp]

void InputManager::initialize() {
    //创建线程“InputReader”
    mReaderThread = new InputReaderThread(mReader);
    //创建线程”InputDispatcher“
    mDispatcherThread = new InputDispatcherThread(mDispatcher);
}

InputReaderThread::InputReaderThread(const sp<InputReaderInterface>& reader) :
        Thread(/*canCallJava*/ true), mReader(reader) {
}

InputDispatcherThread::InputDispatcherThread(const sp<InputDispatcherInterface>& dispatcher) :
        Thread(/*canCallJava*/ true), mDispatcher(dispatcher) {
}

初始化的主要工作就是创建两个能访问Java代码的native线程。

  • 创建线程“InputReader”
  • 创建线程”InputDispatcher“

到此[2.1-2.8]整个的InputManagerService对象初始化过程并完成,接下来便是调用其start方法。

2.9 IMS.start

[-> InputManagerService.java]

public void start() {
    // 启动native对象[见小节2.10]
    nativeStart(mPtr);

    Watchdog.getInstance().addMonitor(this);

    //注册触摸点速度和是否显示功能的观察者
    registerPointerSpeedSettingObserver();
    registerShowTouchesSettingObserver();

    mContext.registerReceiver(new BroadcastReceiver() {
        @Override
        public void onReceive(Context context, Intent intent) {
            updatePointerSpeedFromSettings();
            updateShowTouchesFromSettings();
        }
    }, new IntentFilter(Intent.ACTION_USER_SWITCHED), null, mHandler);

    updatePointerSpeedFromSettings(); //更新触摸点的速度
    updateShowTouchesFromSettings(); //是否在屏幕上显示触摸点
}
2.10 nativeStart

[-> com_android_server_input_InputManagerService.cpp]

static void nativeStart(JNIEnv* env, jclass /* clazz */, jlong ptr) {
    //此处ptr记录的便是NativeInputManager
    NativeInputManager* im = reinterpret_cast<NativeInputManager*>(ptr);
    // [见小节2.11]
    status_t result = im->getInputManager()->start();
    ...
}
2.11 InputManager.start

[InputManager.cpp]

status_t InputManager::start() {
    result = mDispatcherThread->run("InputDispatcher", PRIORITY_URGENT_DISPLAY);
    result = mReaderThread->run("InputReader", PRIORITY_URGENT_DISPLAY);
    ...
    return OK;
}

该方法的主要功能是启动两个线程:

  • 启动线程“InputReader”
  • 启动线程”InputDispatcher“

三. 总结

分层视角:

  1. Java层InputManagerService:采用android.display线程处理Message.
  2. JNI的NativeInputManager:采用android.display线程处理Message,以及创建EventHub。
  3. Native的InputManager:创建InputReaderThread和InputDispatcherThread两个线程

主要功能:

  • IMS服务中的成员变量mPtr记录Native层的NativeInputManager对象;
  • IMS对象的初始化过程的重点在于native初始化,分别创建了以下对象:
    • NativeInputManager;
    • EventHub, InputManager;
    • InputReader,InputDispatcher;
    • InputReaderThread,InputDispatcherThread
  • IMS启动过程的主要功能是启动以下两个线程:
    • InputReader:从EventHub取出事件并处理,再交给InputDispatcher
    • InputDispatcher:接收来自InputReader的输入事件,并派发事件到合适的窗口。

从整个启动过程,可知有system_server进程中有3个线程跟Input输入系统息息相关,分别是android.displayInputReader,InputDispatcher

  • InputDispatcher线程:属于Looper线程,会创建属于自己的Looper,循环分发消息;
  • InputReader线程:通过getEvents()调用EventHub读取输入事件,循环读取消息;
  • android.display线程:属于Looper线程,用于处理Java层的IMS.InputManagerHandler和JNI层的NativeInputManager中指定的MessageHandler消息;

Input事件流程:Linux Kernel -> IMS(InputReader -> InputDispatcher) -> WMS -> ViewRootImpl, 后续再进一步介绍。

四. 附录

最后在列举整个input处理流程中常见的重要对象或结构体,后续input系列文章直接使用以上结构体,可回过来查看。

4.1 InputReader.h

4.1.1 InputDevice
class InputDevice {
  ...
  private:
      InputReaderContext* mContext;
      int32_t mId;
      int32_t mGeneration;
      int32_t mControllerNumber;
      InputDeviceIdentifier mIdentifier;
      String8 mAlias;
      uint32_t mClasses;

      Vector<InputMapper*> mMappers;

      uint32_t mSources;
      bool mIsExternal;
      bool mHasMic;
      bool mDropUntilNextSync;

      typedef int32_t (InputMapper::*GetStateFunc)(uint32_t sourceMask, int32_t code);
      int32_t getState(uint32_t sourceMask, int32_t code, GetStateFunc getStateFunc);

      PropertyMap mConfiguration;
};

4.2 InputDispatcher.h

4.2.1 DropReason
enum DropReason {
   DROP_REASON_NOT_DROPPED = 0, //不丢弃
   DROP_REASON_POLICY = 1, //策略
   DROP_REASON_APP_SWITCH = 2, //应用切换
   DROP_REASON_DISABLED = 3, //disable
   DROP_REASON_BLOCKED = 4, //阻塞
   DROP_REASON_STALE = 5, //过时
};

enum InputTargetWaitCause {
    INPUT_TARGET_WAIT_CAUSE_NONE,
    INPUT_TARGET_WAIT_CAUSE_SYSTEM_NOT_READY, //系统没有准备就绪
    INPUT_TARGET_WAIT_CAUSE_APPLICATION_NOT_READY, //应用没有准备就绪
};

EventEntry* mPendingEvent;
Queue<EventEntry> mInboundQueue; //需要InputDispatcher分发的事件队列
Queue<EventEntry> mRecentQueue;
Queue<CommandEntry> mCommandQueue;

Vector<sp<InputWindowHandle> > mWindowHandles;
sp<InputWindowHandle> mFocusedWindowHandle; //聚焦窗口
sp<InputApplicationHandle> mFocusedApplicationHandle; //聚焦应用
String8 mLastANRState; //上一次ANR时的分发状态

InputTargetWaitCause mInputTargetWaitCause;
nsecs_t mInputTargetWaitStartTime;
nsecs_t mInputTargetWaitTimeoutTime;
bool mInputTargetWaitTimeoutExpired;
//目标等待的应用
sp<InputApplicationHandle> mInputTargetWaitApplicationHandle;
4.2.2 Connection
class Connection : public RefBase {
    enum Status {
        STATUS_NORMAL, //正常状态
        STATUS_BROKEN, //发生无法恢复的错误
        STATUS_ZOMBIE  //input channel被注销掉
    };
    Status status; //状态
    sp<InputChannel> inputChannel; //永不为空
    sp<InputWindowHandle> inputWindowHandle; //可能为空
    bool monitor;
    InputPublisher inputPublisher;
    InputState inputState;

    //当socket占满的同时,应用消费某些输入事件之前无法发布事件,则值为true.
    bool inputPublisherBlocked;

    //需要被发布到connection的事件队列
    Queue<DispatchEntry> outboundQueue;

    //已发布到connection,但还没有收到来自应用的“finished”响应的事件队列
    Queue<DispatchEntry> waitQueue;
}
4.2.3 EventEntry
struct EventEntry : Link<EventEntry> {
     mutable int32_t refCount;
     int32_t type; //时间类型
     nsecs_t eventTime; //事件时间
     uint32_t policyFlags;
     InjectionState* injectionState;

     bool dispatchInProgress; //初始值为false, 分发过程则设置成true
 };

此处type的可取值为:

  • TYPE_CONFIGURATION_CHANGED
  • TYPE_DEVICE_RESET
  • TYPE_KEY: 按键事件
  • TYPE_MOTION: 触摸时间
4.2.4 INPUT_EVENT_INJECTION
enum {
    // 内部使用, 正在执行注入操作
    INPUT_EVENT_INJECTION_PENDING = -1,

    // 事件注入成功
    INPUT_EVENT_INJECTION_SUCCEEDED = 0,

    // 事件注入失败, 由于injector没有权限将聚焦的input事件注入到应用
    INPUT_EVENT_INJECTION_PERMISSION_DENIED = 1,

    // 事件注入失败, 由于没有可用的input target
    INPUT_EVENT_INJECTION_FAILED = 2,

    // 事件注入失败, 由于超时
    INPUT_EVENT_INJECTION_TIMED_OUT = 3
};

4.3 InputTransport.h

4.3.1 InputChannel
class InputChannel : public RefBase {
    // 创建一对input channels
    static status_t openInputChannelPair(const String8& name,
            sp<InputChannel>& outServerChannel, sp<InputChannel>& outClientChannel);

    status_t sendMessage(const InputMessage* msg); //发送消息

    status_t receiveMessage(InputMessage* msg); //接收消息

    //获取InputChannel的fd的拷贝
    sp<InputChannel> dup() const;

private:
    String8 mName;
    int mFd;
};

sendMessage的返回值:

  • OK: 代表成功;
  • WOULD_BLOCK: 代表Channel已满;
  • DEAD_OBJECT: 代表Channel已关闭;

receiveMessage的返回值:

  • OK: 代表成功;
  • WOULD_BLOCK: 代表Channel为空;
  • DEAD_OBJECT: 代表Channel已关闭;
4.3.2 InputTarget
struct InputTarget {
    enum {
        FLAG_FOREGROUND = 1 << 0, //事件分发到前台app

        FLAG_WINDOW_IS_OBSCURED = 1 << 1,

        FLAG_SPLIT = 1 << 2, //MotionEvent被拆分成多窗口

        FLAG_ZERO_COORDS = 1 << 3,

        FLAG_DISPATCH_AS_IS = 1 << 8, //

        FLAG_DISPATCH_AS_OUTSIDE = 1 << 9, //

        FLAG_DISPATCH_AS_HOVER_ENTER = 1 << 10, //

        FLAG_DISPATCH_AS_HOVER_EXIT = 1 << 11, //

        FLAG_DISPATCH_AS_SLIPPERY_EXIT = 1 << 12, //

        FLAG_DISPATCH_AS_SLIPPERY_ENTER = 1 << 13, //

        FLAG_WINDOW_IS_PARTIALLY_OBSCURED = 1 << 14,

        //所有分发模式的掩码
        FLAG_DISPATCH_MASK = FLAG_DISPATCH_AS_IS
                | FLAG_DISPATCH_AS_OUTSIDE
                | FLAG_DISPATCH_AS_HOVER_ENTER
                | FLAG_DISPATCH_AS_HOVER_EXIT
                | FLAG_DISPATCH_AS_SLIPPERY_EXIT
                | FLAG_DISPATCH_AS_SLIPPERY_ENTER,

    };

    sp<InputChannel> inputChannel; //目标的inputChannel

    int32_t flags;

    float xOffset, yOffset; //用于MotionEvent

    float scaleFactor; //用于MotionEvent

    BitSet32 pointerIds;
};
4.3.3 InputPublisher
class InputPublisher {
public:
    //获取输入通道
    inline sp<InputChannel> getChannel() { return mChannel; }

    status_t publishKeyEvent(...); //将key event发送到input channel

    status_t publishMotionEvent(...); //将motion event发送到input channel

    //接收来自InputConsumer发送的完成信号
    status_t receiveFinishedSignal(uint32_t* outSeq, bool* outHandled);

private:
    sp<InputChannel> mChannel;
};
4.3.4 InputConsumer
class InputConsumer {
public:
    inline sp<InputChannel> getChannel() { return mChannel; }

    status_t consume(...); //消费input channel的事件

    //向InputPublisher发送完成信号
    status_t sendFinishedSignal(uint32_t seq, bool handled);

    bool hasDeferredEvent() const;
    bool hasPendingBatch() const;
private:
    sp<InputChannel> mChannel;
    InputMessage mMsg; //当前input消息
    bool mMsgDeferred;

    Vector<Batch> mBatches; //input批量消息
    Vector<TouchState> mTouchStates;
    Vector<SeqChain> mSeqChains;

    status_t consumeBatch(...);
    status_t consumeSamples(...);

    static void initializeKeyEvent(KeyEvent* event, const InputMessage* msg);
    static void initializeMotionEvent(MotionEvent* event, const InputMessage* msg);
}

4.4 input.h

4.4.1 KeyEvent
class KeyEvent : public InputEvent {
    ...
    protected:
        int32_t mAction;
        int32_t mFlags;
        int32_t mKeyCode;
        int32_t mScanCode;
        int32_t mMetaState;
        int32_t mRepeatCount;
        nsecs_t mDownTime; //专指按下时间
        nsecs_t mEventTime; //事件发生时间(包括down/up等事件)
}
4.4.2 MotionEvent
class MotionEvent : public InputEvent {
    ...
    protected:
        int32_t mAction;
        int32_t mActionButton;
        int32_t mFlags;
        int32_t mEdgeFlags;
        int32_t mMetaState;
        int32_t mButtonState;
        float mXOffset;
        float mYOffset;
        float mXPrecision;
        float mYPrecision;
        nsecs_t mDownTime; //按下时间
        Vector<PointerProperties> mPointerProperties;
        Vector<nsecs_t> mSampleEventTimes;
        Vector<PointerCoords> mSamplePointerCoords;
    };
}

4.5 InputListener.h

4.5.1 NotifyKeyArgs
struct NotifyKeyArgs : public NotifyArgs {
    nsecs_t eventTime; //事件发生时间
    int32_t deviceId;
    uint32_t source;
    uint32_t policyFlags;
    int32_t action;
    int32_t flags;
    int32_t keyCode;
    int32_t scanCode;
    int32_t metaState;
    nsecs_t downTime; //按下时间

    ...
};

一. InputReader起点

上一篇文章Input系统—启动篇,介绍IMS服务的启动过程会创建两个native线程,分别是InputReader,InputDispatcher. 接下来从InputReader线程的执行过程从threadLoop为起点开始分析。

1.1 threadLoop

[-> InputReader.cpp]

bool InputReaderThread::threadLoop() {
    mReader->loopOnce(); //【见小节1.2】
    return true;
}

threadLoop返回值true代表的是会不断地循环调用loopOnce()。另外,如果当返回值为false则会 退出循环。整个过程是不断循环的地调用InputReader的loopOnce()方法,先来回顾一下InputReader对象构造方法。

1.2 loopOnce

[-> InputReader.cpp]

void InputReader::loopOnce() {
    ...
    {
        AutoMutex _l(mLock);
        uint32_t changes = mConfigurationChangesToRefresh;
        if (changes) {
            timeoutMillis = 0;
            ...
        } else if (mNextTimeout != LLONG_MAX) {
            nsecs_t now = systemTime(SYSTEM_TIME_MONOTONIC);
            timeoutMillis = toMillisecondTimeoutDelay(now, mNextTimeout);
        }
    }

    //从EventHub读取事件,其中EVENT_BUFFER_SIZE = 256【见小节2.1】
    size_t count = mEventHub->getEvents(timeoutMillis, mEventBuffer, EVENT_BUFFER_SIZE);

    { // acquire lock
        AutoMutex _l(mLock);
         mReaderIsAliveCondition.broadcast();
        if (count) { //处理事件【见小节3.1】
            processEventsLocked(mEventBuffer, count);
        }
        if (oldGeneration != mGeneration) {
            inputDevicesChanged = true;
            getInputDevicesLocked(inputDevices);
        }
        ...
    } // release lock


    if (inputDevicesChanged) { //输入设备发生改变
        mPolicy->notifyInputDevicesChanged(inputDevices);
    }
    //发送事件到nputDispatcher【见小节4.1】
    mQueuedListener->flush();
}

二. EventHub

2.1 getEvents

[-> EventHub.cpp]

size_t EventHub::getEvents(int timeoutMillis, RawEvent* buffer, size_t bufferSize) {
    AutoMutex _l(mLock); //加锁

    struct input_event readBuffer[bufferSize];
    RawEvent* event = buffer; //原始事件
    size_t capacity = bufferSize; //容量大小为256
    bool awoken = false;
    for (;;) {
        nsecs_t now = systemTime(SYSTEM_TIME_MONOTONIC);
        ...

        if (mNeedToScanDevices) {
            mNeedToScanDevices = false;
            scanDevicesLocked(); //扫描设备【见小节2.2】
            mNeedToSendFinishedDeviceScan = true;
        }

        while (mOpeningDevices != NULL) {
            Device* device = mOpeningDevices;
            mOpeningDevices = device->next;
            event->when = now;
            event->deviceId = device->id == mBuiltInKeyboardId ? 0 : device->id;
            event->type = DEVICE_ADDED; //添加设备的事件
            event += 1;
            mNeedToSendFinishedDeviceScan = true;
            if (--capacity == 0) {
                break;
            }
        }
        ...

        bool deviceChanged = false;
        while (mPendingEventIndex < mPendingEventCount) {
            //从mPendingEventItems读取事件项
            const struct epoll_event& eventItem = mPendingEventItems[mPendingEventIndex++];
            ...
            //获取设备ID所对应的device
            ssize_t deviceIndex = mDevices.indexOfKey(eventItem.data.u32);
            Device* device = mDevices.valueAt(deviceIndex);
            if (eventItem.events & EPOLLIN) {
                //从设备不断读取事件,放入到readBuffer
                int32_t readSize = read(device->fd, readBuffer,
                        sizeof(struct input_event) * capacity);

                if (readSize == 0 || (readSize < 0 && errno == ENODEV)) {
                    deviceChanged = true;
                    closeDeviceLocked(device);//设备已被移除则执行关闭操作
                } else if (readSize < 0) {
                    ...
                } else if ((readSize % sizeof(struct input_event)) != 0) {
                    ...
                } else {
                    int32_t deviceId = device->id == mBuiltInKeyboardId ? 0 : device->id;
                    size_t count = size_t(readSize) / sizeof(struct input_event);

                    for (size_t i = 0; i < count; i++) {
                        //获取readBuffer的数据
                        struct input_event& iev = readBuffer[i];
                        //将input_event信息, 封装成RawEvent
                        event->when = nsecs_t(iev.time.tv_sec) * 1000000000LL
                                + nsecs_t(iev.time.tv_usec) * 1000LL;
                        event->deviceId = deviceId;
                        event->type = iev.type;
                        event->code = iev.code;
                        event->value = iev.value;
                        event += 1;
                        capacity -= 1;
                    }
                    if (capacity == 0) {
                        mPendingEventIndex -= 1;
                        break;
                    }
                }
            }
            ...
        }
        ...
        mLock.unlock(); //poll之前先释放锁
        //等待input事件的到来
        int pollResult = epoll_wait(mEpollFd, mPendingEventItems, EPOLL_MAX_EVENTS, timeoutMillis);
        ...
        mLock.lock(); //poll之后再次请求锁

        if (pollResult < 0) { //出现错误
            mPendingEventCount = 0;
            if (errno != EINTR) {
                usleep(100000); //系统发生错误则休眠1s
            }
        } else {
            mPendingEventCount = size_t(pollResult);
        }
    }

    return event - buffer; //返回所读取的事件个数
}

EventHub采用INotify + epoll机制实现监听目录/dev/input下的设备节点,经过EventHub将input_event结构体 + deviceId 转换成RawEvent结构体,如下:

2.1.1 RawEvent

[-> InputEventReader.h]

struct input_event {
 struct timeval time; //事件发生的时间点
 __u16 type;
 __u16 code;
 __s32 value;
};

struct RawEvent {
    nsecs_t when; //事件发生的时间店
    int32_t deviceId; //产生事件的设备Id
    int32_t type; // 事件类型
    int32_t code;
    int32_t value;
};

此处事件类型:

  • DEVICE_ADDED(添加)
  • DEVICE_REMOVED(删除)
  • FINISHED_DEVICE_SCAN(扫描完成)
  • type<FIRST_SYNTHETIC_EVENT(其他事件)

getEvents()已完成转换事件转换工作, 接下来,顺便看看设备扫描过程.

2.2 设备扫描

2.2.1 scanDevicesLocked
void EventHub::scanDevicesLocked() {
    //此处DEVICE_PATH="/dev/input"【见小节2.3】
    status_t res = scanDirLocked(DEVICE_PATH);
    ...
}
2.2.2 scanDirLocked
status_t EventHub::scanDirLocked(const char *dirname)
{
    char devname[PATH_MAX];
    char *filename;
    DIR *dir;
    struct dirent *de;
    dir = opendir(dirname);

    strcpy(devname, dirname);
    filename = devname + strlen(devname);
    *filename++ = '/';
    //读取/dev/input/目录下所有的设备节点
    while((de = readdir(dir))) {
        if(de->d_name[0] == '.' &&
           (de->d_name[1] == '\0' ||
            (de->d_name[1] == '.' && de->d_name[2] == '\0')))
            continue;
        strcpy(filename, de->d_name);
        //打开相应的设备节点【2.2.3】
        openDeviceLocked(devname);
    }
    closedir(dir);
    return 0;
}
2.2.3 openDeviceLocked
status_t EventHub::openDeviceLocked(const char *devicePath) {
    char buffer[80];
    //打开设备文件
    int fd = open(devicePath, O_RDWR | O_CLOEXEC);
    InputDeviceIdentifier identifier;
    //获取设备名
    if(ioctl(fd, EVIOCGNAME(sizeof(buffer) - 1), &buffer) < 1){
    } else {
        buffer[sizeof(buffer) - 1] = '\0';
        identifier.name.setTo(buffer);
    }

    identifier.bus = inputId.bustype;
    identifier.product = inputId.product;
    identifier.vendor = inputId.vendor;
    identifier.version = inputId.version;

    //获取设备物理地址
    if(ioctl(fd, EVIOCGPHYS(sizeof(buffer) - 1), &buffer) < 1) {
    } else {
        buffer[sizeof(buffer) - 1] = '\0';
        identifier.location.setTo(buffer);
    }

    //获取设备唯一ID
    if(ioctl(fd, EVIOCGUNIQ(sizeof(buffer) - 1), &buffer) < 1) {
    } else {
        buffer[sizeof(buffer) - 1] = '\0';
        identifier.uniqueId.setTo(buffer);
    }
    //将identifier信息填充到fd
    assignDescriptorLocked(identifier);
    //设置fd为非阻塞方式
    fcntl(fd, F_SETFL, O_NONBLOCK);

    //获取设备ID,分配设备对象内存
    int32_t deviceId = mNextDeviceId++;
    Device* device = new Device(fd, deviceId, String8(devicePath), identifier);
    ...

    //注册epoll
    struct epoll_event eventItem;
    memset(&eventItem, 0, sizeof(eventItem));
    eventItem.events = EPOLLIN;
    if (mUsingEpollWakeup) {
        eventItem.events |= EPOLLWAKEUP;
    }
    eventItem.data.u32 = deviceId;
    if (epoll_ctl(mEpollFd, EPOLL_CTL_ADD, fd, &eventItem)) {
        delete device; //添加失败则删除该设备
        return -1;
    }
    ...
    //【见小节2.2.4】
    addDeviceLocked(device);
}
2.2.4 addDeviceLocked
void EventHub::addDeviceLocked(Device* device) {
    mDevices.add(device->id, device); //添加到mDevices队列
    device->next = mOpeningDevices;
    mOpeningDevices = device;
}

介绍了EventHub从设备节点获取事件的流程,当收到事件后接下里便开始处理事件。

三. InputReader

3.1 processEventsLocked

[-> InputReader.cpp]

void InputReader::processEventsLocked(const RawEvent* rawEvents, size_t count) {
    for (const RawEvent* rawEvent = rawEvents; count;) {
        int32_t type = rawEvent->type;
        size_t batchSize = 1;
        if (type < EventHubInterface::FIRST_SYNTHETIC_EVENT) {
            int32_t deviceId = rawEvent->deviceId;
            while (batchSize < count) {
                if (rawEvent[batchSize].type >= EventHubInterface::FIRST_SYNTHETIC_EVENT
                        || rawEvent[batchSize].deviceId != deviceId) {
                    break;
                }
                batchSize += 1; //同一设备的事件打包处理
            }
            //数据事件的处理【见小节3.3】
            processEventsForDeviceLocked(deviceId, rawEvent, batchSize);
        } else {
            switch (rawEvent->type) {
            case EventHubInterface::DEVICE_ADDED:
                //设备添加【见小节3.2】
                addDeviceLocked(rawEvent->when, rawEvent->deviceId);
                break;
            case EventHubInterface::DEVICE_REMOVED:
                //设备移除
                removeDeviceLocked(rawEvent->when, rawEvent->deviceId);
                break;
            case EventHubInterface::FINISHED_DEVICE_SCAN:
                //设备扫描完成
                handleConfigurationChangedLocked(rawEvent->when);
                break;
            default:
                ALOG_ASSERT(false);//不会发生
                break;
            }
        }
        count -= batchSize;
        rawEvent += batchSize;
    }
}

事件处理总共有下几类类型:

  • DEVICE_ADDED(设备增加), [见小节3.2]
  • DEVICE_REMOVED(设备移除)
  • FINISHED_DEVICE_SCAN(设备扫描完成)
  • 数据事件[见小节3.4]

先来说说DEVICE_ADDED设备增加的过程。

3.2 设备增加

3.2.1 addDeviceLocked
void InputReader::addDeviceLocked(nsecs_t when, int32_t deviceId) {
    ssize_t deviceIndex = mDevices.indexOfKey(deviceId);
    if (deviceIndex >= 0) {
        return; //已添加的相同设备则不再添加
    }

    InputDeviceIdentifier identifier = mEventHub->getDeviceIdentifier(deviceId);
    uint32_t classes = mEventHub->getDeviceClasses(deviceId);
    int32_t controllerNumber = mEventHub->getDeviceControllerNumber(deviceId);
    //【见小节3.2.2】
    InputDevice* device = createDeviceLocked(deviceId, controllerNumber, identifier, classes);
    device->configure(when, &mConfig, 0);
    device->reset(when);
    mDevices.add(deviceId, device); //添加设备到mDevices
    ...
}
3.2.2 createDeviceLocked
InputDevice* InputReader::createDeviceLocked(int32_t deviceId, int32_t controllerNumber,
        const InputDeviceIdentifier& identifier, uint32_t classes) {
    //创建InputDevice对象
    InputDevice* device = new InputDevice(&mContext, deviceId, bumpGenerationLocked(),
            controllerNumber, identifier, classes);
    ...

    //获取键盘源类型
    uint32_t keyboardSource = 0;
    int32_t keyboardType = AINPUT_KEYBOARD_TYPE_NON_ALPHABETIC;
    if (classes & INPUT_DEVICE_CLASS_KEYBOARD) {
        keyboardSource |= AINPUT_SOURCE_KEYBOARD;
    }
    if (classes & INPUT_DEVICE_CLASS_ALPHAKEY) {
        keyboardType = AINPUT_KEYBOARD_TYPE_ALPHABETIC;
    }
    if (classes & INPUT_DEVICE_CLASS_DPAD) {
        keyboardSource |= AINPUT_SOURCE_DPAD;
    }
    if (classes & INPUT_DEVICE_CLASS_GAMEPAD) {
        keyboardSource |= AINPUT_SOURCE_GAMEPAD;
    }

    //添加键盘类设备InputMapper
    if (keyboardSource != 0) {
        device->addMapper(new KeyboardInputMapper(device, keyboardSource, keyboardType));
    }

    //添加鼠标类设备InputMapper
    if (classes & INPUT_DEVICE_CLASS_CURSOR) {
        device->addMapper(new CursorInputMapper(device));
    }

    //添加触摸屏设备InputMapper
    if (classes & INPUT_DEVICE_CLASS_TOUCH_MT) {
        device->addMapper(new MultiTouchInputMapper(device));
    } else if (classes & INPUT_DEVICE_CLASS_TOUCH) {
        device->addMapper(new SingleTouchInputMapper(device));
    }
    ...
    return device;
}

该方法主要功能:

  • 创建InputDevice对象,将InputReader的mContext赋给InputDevice对象所对应的变量
  • 根据设备类型来创建并添加相对应的InputMapper,同时设置mContext.

input设备类型有很多种,以上代码只列举部分常见的设备以及相应的InputMapper:

  • 键盘类设备:KeyboardInputMapper
  • 触摸屏设备:MultiTouchInputMapper或SingleTouchInputMapper
  • 鼠标类设备:CursorInputMapper

介绍完设备增加过程,继续回到[小节3.1]除了设备的增删,更常见事件便是数据事件,那么接下来介绍数据事件的 处理过程。

3.3 事件处理

3.3.1 processEventsForDeviceLocked
void InputReader::processEventsForDeviceLocked(int32_t deviceId,
        const RawEvent* rawEvents, size_t count) {
    ssize_t deviceIndex = mDevices.indexOfKey(deviceId);
    ...

    InputDevice* device = mDevices.valueAt(deviceIndex);
    if (device->isIgnored()) {
        return; //可忽略则直接返回
    }
    //【见小节3.3.2】
    device->process(rawEvents, count);
}
3.3.2 InputDevice.process
void InputDevice::process(const RawEvent* rawEvents, size_t count) {
    size_t numMappers = mMappers.size();
    for (const RawEvent* rawEvent = rawEvents; count--; rawEvent++) {
        if (mDropUntilNextSync) {
            if (rawEvent->type == EV_SYN && rawEvent->code == SYN_REPORT) {
                mDropUntilNextSync = false;
            }
        } else if (rawEvent->type == EV_SYN && rawEvent->code == SYN_DROPPED) {
            mDropUntilNextSync = true;
            reset(rawEvent->when);
        } else {
            for (size_t i = 0; i < numMappers; i++) {
                InputMapper* mapper = mMappers[i];
                //调用具体mapper来处理【见小节3.4】
                mapper->process(rawEvent);
            }
        }
    }
}

小节[3.2]createDeviceLocked创建设备并添加InputMapper,提到会有多种InputMapper。 这里以KeyboardInputMapper(按键事件)为例来展开说明

3.4 按键事件处理

3.4.1 KeyboardInputMapper.process

[-> InputReader.cpp ::KeyboardInputMapper]

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)) {
            int32_t keyCode;
            //获取所对应的KeyCode【见小节3.4.2】
            if (getEventHub()->mapKey(getDeviceId(), scanCode, usageCode, &keyCode, &flags)) {
                keyCode = AKEYCODE_UNKNOWN;
                flags = 0;
            }
            //【见小节3.4.4】
            processKey(rawEvent->when, rawEvent->value != 0, keyCode, scanCode, flags);
        }
        break;
    }
    case EV_MSC: ...
    case EV_SYN: ...
    }
}
3.4.2 EventHub::mapKey

[-> EventHub.cpp]

status_t EventHub::mapKey(int32_t deviceId,
        int32_t scanCode, int32_t usageCode, int32_t metaState,
        int32_t* outKeycode, int32_t* outMetaState, uint32_t* outFlags) const {
    AutoMutex _l(mLock);
    Device* device = getDeviceLocked(deviceId); //获取设备对象
    status_t status = NAME_NOT_FOUND;

    if (device) {
        sp<KeyCharacterMap> kcm = device->getKeyCharacterMap();
        if (kcm != NULL) {
            //根据scanCode找到keyCode【见小节3.4.3】
            if (!kcm->mapKey(scanCode, usageCode, outKeycode)) {
                *outFlags = 0;
                status = NO_ERROR;
            }
        }
    }
    ...
    return status;
}

将事件的扫描码(scanCode)转换成键盘码(Keycode)

3.4.3 KeyCharacterMap::mapKey

[-> KeyCharacterMap.cpp]

status_t KeyCharacterMap::mapKey(int32_t scanCode, int32_t usageCode, int32_t* outKeyCode) const {
    ...
    if (scanCode) {
        ssize_t index = mKeysByScanCode.indexOfKey(scanCode);
        if (index >= 0) {
            //根据scanCode找到keyCode
            *outKeyCode = mKeysByScanCode.valueAt(index);
            return OK;
        }
    }
    *outKeyCode = AKEYCODE_UNKNOWN;
    return NAME_NOT_FOUND;
}

再回到[3.4.1],接下来进入如下过程:

3.4.4 InputMapper.processKey

[-> InputReader.cpp]

void KeyboardInputMapper::processKey(nsecs_t when, bool down, int32_t keyCode,
        int32_t scanCode, uint32_t policyFlags) {

    if (down) {
        if (mParameters.orientationAware && mParameters.hasAssociatedDisplay) {
            keyCode = rotateKeyCode(keyCode, mOrientation);
        }

        ssize_t keyDownIndex = findKeyDown(scanCode);
        if (keyDownIndex >= 0) {
            //mKeyDowns记录着所有按下的键
            keyCode = mKeyDowns.itemAt(keyDownIndex).keyCode;
        } else {
            ...
            mKeyDowns.push(); //压入栈顶
            KeyDown& keyDown = mKeyDowns.editTop();
            keyDown.keyCode = keyCode;
            keyDown.scanCode = scanCode;
        }
        mDownTime = when; //记录按下时间点

    } else {
        ssize_t keyDownIndex = findKeyDown(scanCode);
        if (keyDownIndex >= 0) {
            //键抬起操作,则移除按下事件
            keyCode = mKeyDowns.itemAt(keyDownIndex).keyCode;
            mKeyDowns.removeAt(size_t(keyDownIndex));
        } else {
            return;  //键盘没有按下操作,则直接忽略抬起操作
        }
    }
    nsecs_t downTime = mDownTime;
    ...

    //创建NotifyKeyArgs对象, when记录eventTime, downTime记录按下时间;
    NotifyKeyArgs args(when, getDeviceId(), mSource, policyFlags,
            down ? AKEY_EVENT_ACTION_DOWN : AKEY_EVENT_ACTION_UP,
            AKEY_EVENT_FLAG_FROM_SYSTEM, keyCode, scanCode, newMetaState, downTime);
    //通知key事件【见小节3.4.5】
    getListener()->notifyKey(&args);
}

参数说明:

  • mKeyDowns记录着所有按下的键;
  • mDownTime记录按下时间点;
  • 此处KeyboardInputMapper的mContext指向InputReader,getListener()获取的便是mQueuedListener。 接下来调用该对象的notifyKey.
3.4.5 QueuedInputListener.notifyKey

[-> InputListener.cpp]

void QueuedInputListener::notifyKey(const NotifyKeyArgs* args) {
    mArgsQueue.push(new NotifyKeyArgs(*args));
}

mArgsQueue的数据类型为Vector<NotifyArgs*>,将该key事件压人该栈顶。 到此,整个事件加工完成, 再然后就是将事件发送给InputDispatcher线程.

四. QueuedListener

4.1 QueuedInputListener.flush

[-> InputListener.cpp]

void QueuedInputListener::flush() {
    size_t count = mArgsQueue.size();
    for (size_t i = 0; i < count; i++) {
        NotifyArgs* args = mArgsQueue[i];
        //【见小节4.2】
        args->notify(mInnerListener);
        delete args;
    }
    mArgsQueue.clear();
}

从InputManager对象初始化的过程可知,mInnerListener便是InputDispatcher对象。

4.2 NotifyKeyArgs.notify

[-> InputListener.cpp]

void NotifyKeyArgs::notify(const sp<InputListenerInterface>& listener) const {
    listener->notifyKey(this); // this是指NotifyKeyArgs【见小节4.3】
}

4.3 InputDispatcher.notifyKey

[-> InputDispatcher.cpp]

void InputDispatcher::notifyKey(const NotifyKeyArgs* args) {
    if (!validateKeyEvent(args->action)) {
        return;
    }
    ...
    int32_t keyCode = args->keyCode;

    if (keyCode == AKEYCODE_HOME) {
        if (args->action == AKEY_EVENT_ACTION_DOWN) {
            property_set("sys.domekey.down", "1");
        } else if (args->action == AKEY_EVENT_ACTION_UP) {
            property_set("sys.domekey.down", "0");
        }
    }

    if (metaState & AMETA_META_ON && args->action == AKEY_EVENT_ACTION_DOWN) {
        ...
    } else if (args->action == AKEY_EVENT_ACTION_UP) {
        ...
    }

    KeyEvent event; //初始化KeyEvent对象
    event.initialize(args->deviceId, args->source, args->action,
            flags, keyCode, args->scanCode, metaState, 0,
            args->downTime, args->eventTime);
    //mPolicy是指NativeInputManager对象。【小节4.3.1】
    mPolicy->interceptKeyBeforeQueueing(&event, /*byref*/ policyFlags);

    bool needWake;
    {
        mLock.lock();
        if (shouldSendKeyToInputFilterLocked(args)) {
            mLock.unlock();
            policyFlags |= POLICY_FLAG_FILTERED;
            //当inputEventObj不为空, 则事件被filter所拦截【见小节4.3.2】
            if (!mPolicy->filterInputEvent(&event, policyFlags)) {
                return;
            }
            mLock.lock();
        }

        int32_t repeatCount = 0;
        //创建KeyEntry对象
        KeyEntry* newEntry = new KeyEntry(args->eventTime,
                args->deviceId, args->source, policyFlags,
                args->action, flags, keyCode, args->scanCode,
                metaState, repeatCount, args->downTime);
        //将KeyEntry放入队列【见小节4.3.3】
        needWake = enqueueInboundEventLocked(newEntry);
        mLock.unlock();
    }

    if (needWake) {
        //唤醒InputDispatcher线程【见小节4.3.5】
        mLooper->wake();
    }
}

该方法的主要功能:

  1. 调用NativeInputManager.interceptKeyBeforeQueueing,加入队列前执行拦截动作,但并不改变流程,调用链:
    • IMS.interceptKeyBeforeQueueing
    • InputMonitor.interceptKeyBeforeQueueing (继承IMS.WindowManagerCallbacks)
    • PhoneWindowManager.interceptKeyBeforeQueueing (继承WindowManagerPolicy)
  2. 当mInputFilterEnabled=true(该值默认为false,可通过setInputFilterEnabled设置),则调用NativeInputManager.filterInputEvent过滤输入事件;
    • 当返回值为false则过滤该事件,不再往下分发;
  3. 生成KeyEvent,并调用enqueueInboundEventLocked,将该事件加入到InputDispatcherd的成员变量mInboundQueue。
4.3.1 interceptKeyBeforeQueueing
void NativeInputManager::interceptKeyBeforeQueueing(const KeyEvent* keyEvent,
        uint32_t& policyFlags) {
    ...
    if ((policyFlags & POLICY_FLAG_TRUSTED)) {
        nsecs_t when = keyEvent->getEventTime(); //时间
        JNIEnv* env = jniEnv();
        jobject keyEventObj = android_view_KeyEvent_fromNative(env, keyEvent);
        if (keyEventObj) {
            // 调用Java层的IMS.interceptKeyBeforeQueueing
            wmActions = env->CallIntMethod(mServiceObj,
                    gServiceClassInfo.interceptKeyBeforeQueueing,
                    keyEventObj, policyFlags);
            ...
        } else {
            ...
        }
        handleInterceptActions(wmActions, when, /*byref*/ policyFlags);
    } else {
        ...
    }
}

该方法会调用Java层的InputManagerService的interceptKeyBeforeQueueing()方法。

4.3.2 filterInputEvent
bool NativeInputManager::filterInputEvent(const InputEvent* inputEvent, uint32_t policyFlags) {
    jobject inputEventObj;

    JNIEnv* env = jniEnv();
    switch (inputEvent->getType()) {
    case AINPUT_EVENT_TYPE_KEY:
        inputEventObj = android_view_KeyEvent_fromNative(env,
                static_cast<const KeyEvent*>(inputEvent));
        break;
    case AINPUT_EVENT_TYPE_MOTION:
        inputEventObj = android_view_MotionEvent_obtainAsCopy(env,
                static_cast<const MotionEvent*>(inputEvent));
        break;
    default:
        return true; // 走事件正常的分发流程
    }

    if (!inputEventObj) {
        return true; // 当inputEventObj为空, 则走事件正常的分发流程
    }

    //当inputEventObj不为空,则调用Java层的IMS.filterInputEvent()
    jboolean pass = env->CallBooleanMethod(mServiceObj, gServiceClassInfo.filterInputEvent,
            inputEventObj, policyFlags);
    if (checkAndClearExceptionFromCallback(env, "filterInputEvent")) {
        pass = true; //出现Exception,则走事件正常的分发流程
    }
    env->DeleteLocalRef(inputEventObj);
    return pass;
}

当inputEventObj不为空,则调用Java层的IMS.filterInputEvent(). 经过层层调用后, 最终会再调用InputDispatcher.injectInputEvent(),该基本等效于该方法的后半段:

  • enqueueInboundEventLocked
  • wakeup
4.3.3 enqueueInboundEventLocked
bool InputDispatcher::enqueueInboundEventLocked(EventEntry* entry) {
    bool needWake = mInboundQueue.isEmpty();
    mInboundQueue.enqueueAtTail(entry); //将该事件放入mInboundQueue队列尾部

    switch (entry->type) {
    case EventEntry::TYPE_KEY: {
        KeyEntry* keyEntry = static_cast<KeyEntry*>(entry);
        if (isAppSwitchKeyEventLocked(keyEntry)) {
            if (keyEntry->action == AKEY_EVENT_ACTION_DOWN) {
                mAppSwitchSawKeyDown = true; //按下事件
            } else if (keyEntry->action == AKEY_EVENT_ACTION_UP) {
                if (mAppSwitchSawKeyDown) {
                    //其中APP_SWITCH_TIMEOUT=500ms
                    mAppSwitchDueTime = keyEntry->eventTime + APP_SWITCH_TIMEOUT;
                    mAppSwitchSawKeyDown = false;
                    needWake = true;
                }
            }
        }
        break;
    }

    case EventEntry::TYPE_MOTION: {
        //当前App无响应且用户希望切换到其他应用窗口,则drop该窗口事件,并处理其他窗口事件
        MotionEntry* motionEntry = static_cast<MotionEntry*>(entry);
        if (motionEntry->action == AMOTION_EVENT_ACTION_DOWN
                && (motionEntry->source & AINPUT_SOURCE_CLASS_POINTER)
                && mInputTargetWaitCause == INPUT_TARGET_WAIT_CAUSE_APPLICATION_NOT_READY
                && mInputTargetWaitApplicationHandle != NULL) {
            int32_t displayId = motionEntry->displayId;
            int32_t x = int32_t(motionEntry->pointerCoords[0].
                    getAxisValue(AMOTION_EVENT_AXIS_X));
            int32_t y = int32_t(motionEntry->pointerCoords[0].
                    getAxisValue(AMOTION_EVENT_AXIS_Y));
            //查询可触摸的窗口【见小节4.3.4】
            sp<InputWindowHandle> touchedWindowHandle = findTouchedWindowAtLocked(displayId, x, y);
            if (touchedWindowHandle != NULL
                    && touchedWindowHandle->inputApplicationHandle
                            != mInputTargetWaitApplicationHandle) {
                mNextUnblockedEvent = motionEntry;
                needWake = true;
            }
        }
        break;
    }
    }

    return needWake;
}

AppSwitchKeyEvent是指keyCode等于以下值:

  • AKEYCODE_HOME
  • AKEYCODE_ENDCALL
  • AKEYCODE_APP_SWITCH
4.3.4 findTouchedWindowAtLocked

[-> InputDispatcher.cpp]

sp<InputWindowHandle> InputDispatcher::findTouchedWindowAtLocked(int32_t displayId,
        int32_t x, int32_t y) {
    //从前台到后台来遍历查询可触摸的窗口
    size_t numWindows = mWindowHandles.size();
    for (size_t i = 0; i < numWindows; i++) {
        sp<InputWindowHandle> windowHandle = mWindowHandles.itemAt(i);
        const InputWindowInfo* windowInfo = windowHandle->getInfo();
        if (windowInfo->displayId == displayId) {
            int32_t flags = windowInfo->layoutParamsFlags;

            if (windowInfo->visible) {
                if (!(flags & InputWindowInfo::FLAG_NOT_TOUCHABLE)) {
                    bool isTouchModal = (flags & (InputWindowInfo::FLAG_NOT_FOCUSABLE
                            | InputWindowInfo::FLAG_NOT_TOUCH_MODAL)) == 0;
                    if (isTouchModal || windowInfo->touchableRegionContainsPoint(x, y)) {
                        return windowHandle; //找到目标窗口
                    }
                }
            }
        }
    }
    return NULL;
}

此处mWindowHandles的赋值过程是由Java层的InputMonitor.setInputWindows(),经过JNI调用后进入InputDispatcher::setInputWindows()方法完成. 进一步说, 就是WMS执行addWindow()过程或许UI改变等场景,都会触发该方法的修改.

4.3.5 Looper.wake

[-> system/core/libutils/Looper.cpp]

void Looper::wake() {
    uint64_t inc = 1;

    ssize_t nWrite = TEMP_FAILURE_RETRY(write(mWakeEventFd, &inc, sizeof(uint64_t)));
    if (nWrite != sizeof(uint64_t)) {
        if (errno != EAGAIN) {
            ALOGW("Could not write wake signal, errno=%d", errno);
        }
    }
}

[小节4.3]的过程会调用enqueueInboundEventLocked()方法来决定是否需要将数字1写入句柄mWakeEventFd来唤醒InputDispatcher线程. 满足唤醒的条件:

  1. 执行enqueueInboundEventLocked方法前,mInboundQueue队列为空,执行完必然不再为空,则需要唤醒分发线程;
  2. 当事件类型为key事件,且发生一对按下和抬起操作,则需要唤醒;
  3. 当事件类型为motion事件,且当前可触摸的窗口属于另一个应用,则需要唤醒.

五. 总结

5.1 核心工作

InputReader整个过程涉及多次事件封装转换,其主要工作核心是以下三大步骤:

  • getEvents:通过EventHub(监听目录/dev/input)读取事件放入mEventBuffer,而mEventBuffer是一个大小为256的数组, 再将事件input_event转换为RawEvent; [见小节2.1]
  • processEventsLocked: 对事件进行加工, 转换RawEvent -> NotifyKeyArgs(NotifyArgs) [见小节3.1]
  • QueuedListener->flush:将事件发送到InputDispatcher线程, 转换NotifyKeyArgs -> KeyEntry(EventEntry) [见小节4.1]

InputReader线程不断循环地执行InputReader.loopOnce(), 每次处理完生成的是EventEntry(比如KeyEntry, MotionEntry), 接下来的工作就交给InputDispatcher线程。

5.2 流程图

点击查看大图:

input_reader_seq

InputReader的核心工作就是从EventHub获取数据后生成EventEntry事件,加入到InputDispatcher的mInboundQueue队列,再唤醒InputDispatcher线程。

input_reader

说明:

  • IMS.filterInputEvent可以过滤无需上报的事件,当该方法返回值为false则代表是需要被过滤掉的事件,无机会交给InputDispatcher来分发。
  • 节点/dev/input的event事件所对应的输入设备信息位于/proc/bus/input/devices,也可以通过getevent来获取事件. 不同的input事件所对应的物理input节点,比如常见的情形:
    • 屏幕触摸和(MENU,HOME,BACK)3按键:对应同一个input设备节点;
    • POWER和音量(下)键:对应同一个input设备节点;
    • 音量(上)键:对应同一个input设备节点;

一. InputDispatcher起点

上篇文章输入系统之InputReader线程,介绍InputReader利用EventHub获取数据后生成EventEntry事件,加入到InputDispatcher的mInboundQueue队列,再唤醒InputDispatcher线程。本文将介绍InputDispatcher,同样从threadLoop为起点开始分析。

1.1 threadLoop

先来回顾一下InputDispatcher对象的初始化过程:

InputDispatcher::InputDispatcher(const sp<InputDispatcherPolicyInterface>& policy) :
    mPolicy(policy),
    mPendingEvent(NULL), mLastDropReason(DROP_REASON_NOT_DROPPED),
    mAppSwitchSawKeyDown(false), mAppSwitchDueTime(LONG_LONG_MAX),
    mNextUnblockedEvent(NULL),
    mDispatchEnabled(false), mDispatchFrozen(false), mInputFilterEnabled(false),
    mInputTargetWaitCause(INPUT_TARGET_WAIT_CAUSE_NONE) {
    //创建Looper对象
    mLooper = new Looper(false);

    mKeyRepeatState.lastKeyEntry = NULL;
    //获取分发超时参数
    policy->getDispatcherConfiguration(&mConfig);
}

该方法主要工作:

  • 创建属于自己线程的Looper对象;
  • 超时参数来自于IMS,参数默认值keyRepeatTimeout = 500,keyRepeatDelay = 50。

[-> InputDispatcher.cpp]

bool InputDispatcherThread::threadLoop() {
    mDispatcher->dispatchOnce(); //【见小节1.2】
    return true;
}

整个过程不断循环地调用InputDispatcher的dispatchOnce()来分发事件

1.2 dispatchOnce

[-> InputDispatcher.cpp]

void InputDispatcher::dispatchOnce() {
    nsecs_t nextWakeupTime = LONG_LONG_MAX;
    {
        AutoMutex _l(mLock);
        //唤醒等待线程,monitor()用于监控dispatcher是否发生死锁
        mDispatcherIsAliveCondition.broadcast();

        if (!haveCommandsLocked()) {
            //当mCommandQueue不为空时处理【见小节2.1】
            dispatchOnceInnerLocked(&nextWakeupTime);
        }

        //【见小节3.1】
        if (runCommandsLockedInterruptible()) {
            nextWakeupTime = LONG_LONG_MIN;
        }
    }

    nsecs_t currentTime = now();
    int timeoutMillis = toMillisecondTimeoutDelay(currentTime, nextWakeupTime);
    mLooper->pollOnce(timeoutMillis); //进入epoll_wait
}

线程执行Looper->pollOnce,进入epoll_wait等待状态,当发生以下任一情况则退出等待状态:

  1. callback:通过回调方法来唤醒;
  2. timeout:到达nextWakeupTime时间,超时唤醒;
  3. wake: 主动调用Looper的wake()方法;

二. InputDispatcher

2.1 dispatchOnceInnerLocked

void InputDispatcher::dispatchOnceInnerLocked(nsecs_t* nextWakeupTime) {
    nsecs_t currentTime = now(); //当前时间

    if (!mDispatchEnabled) { //默认值为false
        resetKeyRepeatLocked(); //重置操作
    }
    if (mDispatchFrozen) { //默认值为false
        return; //当分发被冻结,则不再处理超时和分发事件的工作,直接返回
    }

    //优化app切换延迟,当切换超时,则抢占分发,丢弃其他所有即将要处理的事件。
    bool isAppSwitchDue = mAppSwitchDueTime <= currentTime;
    ...

    if (!mPendingEvent) {
        if (mInboundQueue.isEmpty()) {
            if (!mPendingEvent) {
                return; //没有事件需要处理,则直接返回
            }
        } else {
            //从mInboundQueue取出头部的事件
            mPendingEvent = mInboundQueue.dequeueAtHead();
        }
        ...
        resetANRTimeoutsLocked(); //重置ANR信息[见小节2.1.1]
    }

    bool done = false;
    DropReason dropReason = DROP_REASON_NOT_DROPPED;
    if (!(mPendingEvent->policyFlags & POLICY_FLAG_PASS_TO_USER)) {
        dropReason = DROP_REASON_POLICY;
    } else if (!mDispatchEnabled) {
        dropReason = DROP_REASON_DISABLED;
    }
    ...

    switch (mPendingEvent->type) {
      case EventEntry::TYPE_KEY: {
          KeyEntry* typedEntry = static_cast<KeyEntry*>(mPendingEvent);
          if (isAppSwitchDue) {
              if (isAppSwitchKeyEventLocked(typedEntry)) {
                  resetPendingAppSwitchLocked(true);
                  isAppSwitchDue = false;
              } else if (dropReason == DROP_REASON_NOT_DROPPED) {
                  dropReason = DROP_REASON_APP_SWITCH;
              }
          }
          if (dropReason == DROP_REASON_NOT_DROPPED
                  && isStaleEventLocked(currentTime, typedEntry)) {
              dropReason = DROP_REASON_STALE;
          }
          if (dropReason == DROP_REASON_NOT_DROPPED && mNextUnblockedEvent) {
              dropReason = DROP_REASON_BLOCKED;
          }
          // 分发按键事件[见小节2.2]
          done = dispatchKeyLocked(currentTime, typedEntry, &dropReason, nextWakeupTime);
          break;
      }
      ...
    }
    ...

    //分发操作完成,则进入该分支
    if (done) {
        if (dropReason != DROP_REASON_NOT_DROPPED) {
            //[见小节2.1.2]
            dropInboundEventLocked(mPendingEvent, dropReason);
        }
        mLastDropReason = dropReason;
        releasePendingEventLocked(); //释放pending事件见小节2.10]
        *nextWakeupTime = LONG_LONG_MIN; //强制立刻执行轮询
    }
}

在enqueueInboundEventLocked()的过程中已设置mAppSwitchDueTime等于eventTime加上500ms:

mAppSwitchDueTime = keyEntry->eventTime + APP_SWITCH_TIMEOUT;

该方法主要功能:

  1. mDispatchFrozen用于决定是否冻结事件分发工作不再往下执行;
  2. 当事件分发的时间点距离该事件加入mInboundQueue的时间超过500ms,则认为app切换过期,即isAppSwitchDue=true;
  3. mInboundQueue不为空,则取出头部的事件,放入mPendingEvent变量;并重置ANR时间;
  4. 根据EventEntry的type类型分别处理,比如按键调用dispatchKeyLocked分发事件;再根据分发结果来决定是否进入done;
  5. 执行完成(done)的处理:
    • 根据dropReason(默认NOT_DROPPED不处理)来决定是否丢失事件; dropInboundEventLocked
    • 释放当前正在处理的事件(即mPendingEvent); releasePendingEventLocked

关于dispatchKeyLocked分发事件,

  1. 不会执行done过情况:
    • 当前Event时间小于唤醒时间;
    • 让policy有机会执行拦截操作;
    • 调用findFocusedWindowTargetsLocked方法的返回结果是INPUT_EVENT_INJECTION_PENDING, 即targets没有处于Ready状态;
  2. 会执行done的情况:
    • 该事件需要丢弃, 即dropReason != DROP_REASON_NOT_DROPPED;
    • findFocusedWindowTargetsLocked的返回结果不是INPUT_EVENT_INJECTION_PENDING(没有正在处理的事件);

接下来以按键为例来展开说明, 则进入[小节2.2] dispatchKeyLocked.

2.1.1 resetANRTimeoutsLocked
void InputDispatcher::resetANRTimeoutsLocked() {
    // 重置等待超时cause和handle
    mInputTargetWaitCause = INPUT_TARGET_WAIT_CAUSE_NONE;
    mInputTargetWaitApplicationHandle.clear();
}
2.1.2 dropInboundEventLocked
void InputDispatcher::dropInboundEventLocked(EventEntry* entry, DropReason dropReason) {
    const char* reason;
    switch (dropReason) {
    case DROP_REASON_POLICY:
        reason = "inbound event was dropped because the policy consumed it";
        break;
    case DROP_REASON_DISABLED:
        if (mLastDropReason != DROP_REASON_DISABLED) {
            ALOGI("Dropped event because input dispatch is disabled.");
        }
        reason = "inbound event was dropped because input dispatch is disabled";
        break;
    case DROP_REASON_APP_SWITCH:
        ALOGI("Dropped event because of pending overdue app switch.");
        reason = "inbound event was dropped because of pending overdue app switch";
        break;
    case DROP_REASON_BLOCKED:
        ALOGI("Dropped event because the current application is not responding and the user "
                "has started interacting with a different application.");
        reason = "inbound event was dropped because the current application is not responding "
                "and the user has started interacting with a different application";
        break;
    case DROP_REASON_STALE:
        ALOGI("Dropped event because it is stale.");
        reason = "inbound event was dropped because it is stale";
        break;
    default:
        return;
    }

    switch (entry->type) {
    case EventEntry::TYPE_KEY: {
        CancelationOptions options(CancelationOptions::CANCEL_NON_POINTER_EVENTS, reason);
        synthesizeCancelationEventsForAllConnectionsLocked(options);
        break;
    }
    ...
    }
}

2.2 dispatchKeyLocked

bool InputDispatcher::dispatchKeyLocked(nsecs_t currentTime, KeyEntry* entry,
        DropReason* dropReason, nsecs_t* nextWakeupTime) {
    ...
    if (entry->interceptKeyResult == KeyEntry::INTERCEPT_KEY_RESULT_TRY_AGAIN_LATER) {
        // case1: 当前时间小于唤醒时间,则进入等待状态。
        if (currentTime < entry->interceptKeyWakeupTime) {
            if (entry->interceptKeyWakeupTime < *nextWakeupTime) {
                *nextWakeupTime = entry->interceptKeyWakeupTime;
            }
            return false; //直接返回
        }
        entry->interceptKeyResult = KeyEntry::INTERCEPT_KEY_RESULT_UNKNOWN;
        entry->interceptKeyWakeupTime = 0;
    }

    if (entry->interceptKeyResult == KeyEntry::INTERCEPT_KEY_RESULT_UNKNOWN) {
        //case2: 让policy有机会执行拦截操作
        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; //直接返回
        } 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;
        }
    }

    //case3: 如果需要丢弃该事件,则执行清理操作
    if (*dropReason != DROP_REASON_NOT_DROPPED) {
        setInjectionResultLocked(entry, *dropReason == DROP_REASON_POLICY
                ? INPUT_EVENT_INJECTION_SUCCEEDED : INPUT_EVENT_INJECTION_FAILED);
        return true; //直接返回
    }

    Vector<InputTarget> inputTargets;
    //case4: 寻找焦点 【见小节2.3】
    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);

    //只有injectionResult是成功,才有机会执行分发事件【见小节2.5】
    dispatchEventLocked(currentTime, entry, inputTargets);
    return true;
}

在以下场景下,有可能无法分发事件:

  1. 当前时间小于唤醒时间(nextWakeupTime)的情况;
  2. policy需要提前拦截事件的情况;
  3. 需要drop事件的情况;
  4. 寻找聚焦窗口失败的情况;

如果成功跳过以上所有情况,则会进入执行事件分发的过程。

2.3 findFocusedWindowTargetsLocked

int32_t InputDispatcher::findFocusedWindowTargetsLocked(nsecs_t currentTime,
        const EventEntry* entry, Vector<InputTarget>& inputTargets, nsecs_t* nextWakeupTime) {
    int32_t injectionResult;
    String8 reason;

    if (mFocusedWindowHandle == NULL) {
        if (mFocusedApplicationHandle != NULL) {
            //【见小节2.3.2】
            injectionResult = handleTargetsNotReadyLocked(currentTime, entry,
                    mFocusedApplicationHandle, NULL, nextWakeupTime,
                    "Waiting because no window has focus but there is a "
                    "focused application that may eventually add a window "
                    "when it finishes starting up.");
            goto Unresponsive;
        }

        ALOGI("Dropping event because there is no focused window or focused application.");
        injectionResult = INPUT_EVENT_INJECTION_FAILED;
        goto Failed;
    }

    //权限检查
    if (! checkInjectionPermission(mFocusedWindowHandle, entry->injectionState)) {
        injectionResult = INPUT_EVENT_INJECTION_PERMISSION_DENIED;
        goto Failed;
    }

    //检测窗口是否为更多的输入操作而准备就绪【见小节2.3.1】
    reason = checkWindowReadyForMoreInputLocked(currentTime,
            mFocusedWindowHandle, entry, "focused");
    if (!reason.isEmpty()) {
        //【见小节2.3.2】
        injectionResult = handleTargetsNotReadyLocked(currentTime, entry,
                mFocusedApplicationHandle, mFocusedWindowHandle, nextWakeupTime, reason.string());
        goto Unresponsive;
    }

    injectionResult = INPUT_EVENT_INJECTION_SUCCEEDED;
    //成功找到目标窗口,添加到目标窗口 [见小节2.3.3]
    addWindowTargetLocked(mFocusedWindowHandle,
            InputTarget::FLAG_FOREGROUND | InputTarget::FLAG_DISPATCH_AS_IS, BitSet32(0),
            inputTargets);

Failed:
Unresponsive:
    //TODO: 统计等待时长信息,目前没有实现,这个方法还是很值得去改造
    nsecs_t timeSpentWaitingForApplication = getTimeSpentWaitingForApplicationLocked(currentTime);
    updateDispatchStatisticsLocked(currentTime, entry,
          injectionResult, timeSpentWaitingForApplication);
    return injectionResult;
}

此处mFocusedWindowHandle是何处赋值呢?是在InputDispatcher.setInputWindows()方法,具体见下一篇文章Input系统—UI线程.

寻找聚焦窗口失败的情况:

  • 无窗口,无应用:Dropping event because there is no focused window or focused application.(这并不导致ANR的情况,因为没有机会调用handleTargetsNotReadyLocked)
  • 无窗口, 有应用:Waiting because no window has focus but there is a focused application that may eventually add a window when it finishes starting up.

另外,还有更多多的失败场景见checkWindowReadyForMoreInputLocked的过程,如下:

2.3.1 checkWindowReadyForMoreInputLocked
String8 InputDispatcher::checkWindowReadyForMoreInputLocked(nsecs_t currentTime,
        const sp<InputWindowHandle>& windowHandle, const EventEntry* eventEntry,
        const char* targetType) {
    //当窗口暂停的情况,则保持等待
    if (windowHandle->getInfo()->paused) {
        return String8::format("Waiting because the %s window is paused.", targetType);
    }

    //当窗口连接未注册,则保持等待
    ssize_t connectionIndex = getConnectionIndexLocked(windowHandle->getInputChannel());
    if (connectionIndex < 0) {
        return String8::format("Waiting because the %s window's input channel is not "
                "registered with the input dispatcher.  The window may be in the process "
                "of being removed.", targetType);
    }

    //当窗口连接已死亡,则保持等待
    sp<Connection> connection = mConnectionsByFd.valueAt(connectionIndex);
    if (connection->status != Connection::STATUS_NORMAL) {
        return String8::format("Waiting because the %s window's input connection is %s."
                "The window may be in the process of being removed.", targetType,
                connection->getStatusLabel());
    }

    // 当窗口连接已满,则保持等待
    if (connection->inputPublisherBlocked) {
        return String8::format("Waiting because the %s window's input channel is full.  "
                "Outbound queue length: %d.  Wait queue length: %d.",
                targetType, connection->outboundQueue.count(), connection->waitQueue.count());
    }


    if (eventEntry->type == EventEntry::TYPE_KEY) {
        // 按键事件,输出队列或事件等待队列不为空
        if (!connection->outboundQueue.isEmpty() || !connection->waitQueue.isEmpty()) {
            return String8::format("Waiting to send key event because the %s window has not "
                    "finished processing all of the input events that were previously "
                    "delivered to it.  Outbound queue length: %d.  Wait queue length: %d.",
                    targetType, connection->outboundQueue.count(), connection->waitQueue.count());
        }
    } else {
        // 非按键事件,事件等待队列不为空且头事件分发超时500ms
        if (!connection->waitQueue.isEmpty()
                && currentTime >= connection->waitQueue.head->deliveryTime
                        + STREAM_AHEAD_EVENT_TIMEOUT) {
            return String8::format("Waiting to send non-key event because the %s window has not "
                    "finished processing certain input events that were delivered to it over "
                    "%0.1fms ago.  Wait queue length: %d.  Wait queue head age: %0.1fms.",
                    targetType, STREAM_AHEAD_EVENT_TIMEOUT * 0.000001f,
                    connection->waitQueue.count(),
                    (currentTime - connection->waitQueue.head->deliveryTime) * 0.000001f);
        }
    }
    return String8::empty();
}
2.3.2 handleTargetsNotReadyLocked
int32_t InputDispatcher::handleTargetsNotReadyLocked(nsecs_t currentTime,
    const EventEntry* entry,
    const sp<InputApplicationHandle>& applicationHandle,
    const sp<InputWindowHandle>& windowHandle,
    nsecs_t* nextWakeupTime, const char* reason) {
    if (applicationHandle == NULL && windowHandle == NULL) {
        if (mInputTargetWaitCause != INPUT_TARGET_WAIT_CAUSE_SYSTEM_NOT_READY) {
            mInputTargetWaitCause = INPUT_TARGET_WAIT_CAUSE_SYSTEM_NOT_READY;
            mInputTargetWaitStartTime = currentTime; //当前时间
            mInputTargetWaitTimeoutTime = LONG_LONG_MAX;
            mInputTargetWaitTimeoutExpired = false;
            mInputTargetWaitApplicationHandle.clear();
        }
    } else {
        if (mInputTargetWaitCause != INPUT_TARGET_WAIT_CAUSE_APPLICATION_NOT_READY) {
            nsecs_t timeout;
            if (windowHandle != NULL) {
                timeout = windowHandle->getDispatchingTimeout(DEFAULT_INPUT_DISPATCHING_TIMEOUT);
            } else if (applicationHandle != NULL) {
                timeout = applicationHandle->getDispatchingTimeout(DEFAULT_INPUT_DISPATCHING_TIMEOUT);
            } else {
                timeout = DEFAULT_INPUT_DISPATCHING_TIMEOUT; // 5s
            }

            mInputTargetWaitCause = INPUT_TARGET_WAIT_CAUSE_APPLICATION_NOT_READY;
            mInputTargetWaitStartTime = currentTime; //当前时间
            mInputTargetWaitTimeoutTime = currentTime + timeout;
            mInputTargetWaitTimeoutExpired = false;
            mInputTargetWaitApplicationHandle.clear();

            if (windowHandle != NULL) {
                mInputTargetWaitApplicationHandle = windowHandle->inputApplicationHandle;
            }
            if (mInputTargetWaitApplicationHandle == NULL && applicationHandle != NULL) {
                mInputTargetWaitApplicationHandle = applicationHandle;
            }
        }
    }

    if (mInputTargetWaitTimeoutExpired) {
        return INPUT_EVENT_INJECTION_TIMED_OUT; //等待超时已过期,则直接返回
    }

    //当超时5s则进入ANR流程
    if (currentTime >= mInputTargetWaitTimeoutTime) {
        onANRLocked(currentTime, applicationHandle, windowHandle,
                entry->eventTime, mInputTargetWaitStartTime, reason);

        *nextWakeupTime = LONG_LONG_MIN; //强制立刻执行轮询来执行ANR策略
        return INPUT_EVENT_INJECTION_PENDING;
    } else {
        if (mInputTargetWaitTimeoutTime < *nextWakeupTime) {
            *nextWakeupTime = mInputTargetWaitTimeoutTime; //当触发超时则强制执行轮询
        }
        return INPUT_EVENT_INJECTION_PENDING;
    }
}

此处mInputTargetWaitTimeoutTime是由当前时间戳+5s, 并设置mInputTargetWaitCause等于INPUT_TARGET_WAIT_CAUSE_APPLICATION_NOT_READY. 也就是说ANR时间段是指input等待理由处于INPUT_TARGET_WAIT_CAUSE_APPLICATION_NOT_READY(应用没有准备就绪)的时间长达5s的场景.而前面resetANRTimeoutsLocked() 过程是唯一用于重置等待理由的地方.

那么, ANR时间区间是指当前这次的事件dispatch过程中执行findFocusedWindowTargetsLocked()方法到下一次执行resetANRTimeoutsLocked()的时间区间.

  • 当applicationHandle和windowHandle同时为空, 且system准备就绪的情况下
    • 设置等待理由 INPUT_TARGET_WAIT_CAUSE_SYSTEM_NOT_READY;
    • 设置超时等待时长为无限大;
    • 设置TimeoutExpired= false
    • 清空等待队列;
  • 当applicationHandle和windowHandle至少一个不为空, 且application准备就绪的情况下:
    • 设置等待理由 INPUT_TARGET_WAIT_CAUSE_APPLICATION_NOT_READY;
    • 设置超时等待时长为5s;
    • 设置TimeoutExpired= false
    • 清空等待队列;

继续回到[小节2.3]findFocusedWindowTargetsLocked,如果没有发生ANR,则addWindowTargetLocked()将该事件添加到inputTargets。

2.3.3 addWindowTargetLocked
void InputDispatcher::addWindowTargetLocked(const sp<InputWindowHandle>& windowHandle,
        int32_t targetFlags, BitSet32 pointerIds, Vector<InputTarget>& inputTargets) {
    inputTargets.push();

    const InputWindowInfo* windowInfo = windowHandle->getInfo();
    InputTarget& target = inputTargets.editTop();
    target.inputChannel = windowInfo->inputChannel;
    target.flags = targetFlags;
    target.xOffset = - windowInfo->frameLeft;
    target.yOffset = - windowInfo->frameTop;
    target.scaleFactor = windowInfo->scaleFactor;
    target.pointerIds = pointerIds;
}

将当前聚焦窗口mFocusedWindowHandle的inputChannel传递到inputTargets。

2.4 dispatchEventLocked

void InputDispatcher::dispatchEventLocked(nsecs_t currentTime,
        EventEntry* eventEntry, const Vector<InputTarget>& inputTargets) {
    //【见小节2.4.1】向mCommandQueue队列添加doPokeUserActivityLockedInterruptible命令
    pokeUserActivityLocked(eventEntry);

    for (size_t i = 0; i < inputTargets.size(); i++) {
        const InputTarget& inputTarget = inputTargets.itemAt(i);
        //[见小节2.4.3]
        ssize_t connectionIndex = getConnectionIndexLocked(inputTarget.inputChannel);
        if (connectionIndex >= 0) {
            sp<Connection> connection = mConnectionsByFd.valueAt(connectionIndex);
            //找到目标连接[见小节2.5]
            prepareDispatchCycleLocked(currentTime, connection, eventEntry, &inputTarget);
        }
    }
}

该方法主要功能是将eventEntry发送到目标inputTargets.

其中pokeUserActivityLocked(eventEntry)方法最终会调用到Java层的PowerManagerService.java中的userActivityFromNative()方法. 这也是PMS中唯一的native call方法.

2.4.1 pokeUserActivityLocked
void InputDispatcher::pokeUserActivityLocked(const EventEntry* eventEntry) {
    if (mFocusedWindowHandle != NULL) {
        const InputWindowInfo* info = mFocusedWindowHandle->getInfo();
        if (info->inputFeatures & InputWindowInfo::INPUT_FEATURE_DISABLE_USER_ACTIVITY) {
            return;
        }
    }
    ...
    //【见小节2.4.2】
    CommandEntry* commandEntry = postCommandLocked(
            & InputDispatcher::doPokeUserActivityLockedInterruptible);
    commandEntry->eventTime = eventEntry->eventTime;
    commandEntry->userActivityEventType = eventType;
}
2.4.2 postCommandLocked
InputDispatcher::CommandEntry* InputDispatcher::postCommandLocked(Command command) {
    CommandEntry* commandEntry = new CommandEntry(command);
    // 将命令加入mCommandQueue队尾
    mCommandQueue.enqueueAtTail(commandEntry);
    return commandEntry;
}
2.4.3 getConnectionIndexLocked
ssize_t InputDispatcher::getConnectionIndexLocked(const sp<InputChannel>& inputChannel) {
    ssize_t connectionIndex = mConnectionsByFd.indexOfKey(inputChannel->getFd());
    if (connectionIndex >= 0) {
        sp<Connection> connection = mConnectionsByFd.valueAt(connectionIndex);
        if (connection->inputChannel.get() == inputChannel.get()) {
            return connectionIndex;
        }
    }
    return -1;
}

根据inputChannel的fd从mConnectionsByFd队列中查询目标connection.

2.5 prepareDispatchCycleLocked

void InputDispatcher::prepareDispatchCycleLocked(nsecs_t currentTime,
        const sp<Connection>& connection, EventEntry* eventEntry, const InputTarget* inputTarget) {

    if (connection->status != Connection::STATUS_NORMAL) {
        return; //当连接已破坏,则直接返回
    }
    ...

    //[见小节2.6]
    enqueueDispatchEntriesLocked(currentTime, connection, eventEntry, inputTarget);
}

当connection状态不正确,则直接返回。

2.6 enqueueDispatchEntriesLocked

void InputDispatcher::enqueueDispatchEntriesLocked(nsecs_t currentTime,
        const sp<Connection>& connection, EventEntry* eventEntry, const InputTarget* inputTarget) {
    bool wasEmpty = connection->outboundQueue.isEmpty();

    //[见小节2.7]
    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 (wasEmpty && !connection->outboundQueue.isEmpty()) {
        //当原先的outbound队列为空, 且当前outbound不为空的情况执行.[见小节2.8]
        startDispatchCycleLocked(currentTime, connection);
    }
}

该方法主要功能:

  • 根据dispatchMode来分别执行DispatchEntry事件加入队列的操作。
  • 当起初connection.outboundQueue等于空, 经enqueueDispatchEntryLocked处理后, outboundQueue不等于空情况下, 则执行startDispatchCycleLocked()方法.

2.7 enqueueDispatchEntryLocked

void InputDispatcher::enqueueDispatchEntryLocked(
        const sp<Connection>& connection, EventEntry* eventEntry, const InputTarget* inputTarget,
        int32_t dispatchMode) {
    int32_t inputTargetFlags = inputTarget->flags;
    if (!(inputTargetFlags & dispatchMode)) {
        return; //分发模式不匹配,则直接返回
    }
    inputTargetFlags = (inputTargetFlags & ~InputTarget::FLAG_DISPATCH_MASK) | dispatchMode;

    //生成新的事件, 加入connection的outbound队列
    DispatchEntry* dispatchEntry = new DispatchEntry(eventEntry,
            inputTargetFlags, inputTarget->xOffset, inputTarget->yOffset,
            inputTarget->scaleFactor);

    switch (eventEntry->type) {
        case EventEntry::TYPE_KEY: {
            KeyEntry* keyEntry = static_cast<KeyEntry*>(eventEntry);
            dispatchEntry->resolvedAction = keyEntry->action;
            dispatchEntry->resolvedFlags = keyEntry->flags;

            if (!connection->inputState.trackKey(keyEntry,
                    dispatchEntry->resolvedAction, dispatchEntry->resolvedFlags)) {
                delete dispatchEntry;
                return; //忽略不连续的事件
            }
            break;
        }
        ...
    }
    ...

    //添加到outboundQueue队尾
    connection->outboundQueue.enqueueAtTail(dispatchEntry);
}

该方法主要功能:

  • 根据dispatchMode来决定是否需要加入outboundQueue队列;
  • 根据EventEntry,来生成DispatchEntry事件;
  • 将dispatchEntry加入到connection的outbound队列.

执行到这里,其实等于由做了一次搬运的工作,将InputDispatcher中mInboundQueue中的事件取出后, 找到目标window后,封装dispatchEntry加入到connection的outbound队列.

2.8 startDispatchCycleLocked

void InputDispatcher::startDispatchCycleLocked(nsecs_t currentTime,
        const sp<Connection>& connection) {

    //当Connection状态正常,且outboundQueue不为空
    while (connection->status == Connection::STATUS_NORMAL
            && !connection->outboundQueue.isEmpty()) {
        DispatchEntry* dispatchEntry = connection->outboundQueue.head;
        dispatchEntry->deliveryTime = currentTime; //设置deliveryTime时间

        status_t status;
        EventEntry* eventEntry = dispatchEntry->eventEntry;
        switch (eventEntry->type) {
          case EventEntry::TYPE_KEY: {
              KeyEntry* keyEntry = static_cast<KeyEntry*>(eventEntry);

              //发布Key事件 [见小节2.9]
              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;
          }
          ...
        }

        if (status) { //publishKeyEvent失败情况
            if (status == WOULD_BLOCK) {
                if (connection->waitQueue.isEmpty()) {
                    //pipe已满,但waitQueue为空. 不正常的行为
                    abortBrokenDispatchCycleLocked(currentTime, connection, true /*notify*/);
                } else {
                    // 处于阻塞状态
                    connection->inputPublisherBlocked = true;
                }
            } else {
                //不不正常的行为
                abortBrokenDispatchCycleLocked(currentTime, connection, true /*notify*/);
            }
            return;
        }

        //从outboundQueue中取出事件,重新放入waitQueue队列
        connection->outboundQueue.dequeue(dispatchEntry);
        connection->waitQueue.enqueueAtTail(dispatchEntry);

    }
}

startDispatchCycleLocked的主要功能: 从outboundQueue中取出事件,重新放入waitQueue队列

  • startDispatchCycleLocked触发时机:当起初connection.outboundQueue等于空, 经enqueueDispatchEntryLocked处理后, outboundQueue不等于空。
  • startDispatchCycleLocked主要功能: 从outboundQueue中取出事件,重新放入waitQueue队列
  • publishKeyEvent执行结果status不等于OK的情况下:
    • WOULD_BLOCK,且waitQueue等于空,则调用abortBrokenDispatchCycleLocked(),该方法最终会调用到Java层的IMS.notifyInputChannelBroken().
    • WOULD_BLOCK,且waitQueue不等于空,则处于阻塞状态,即inputPublisherBlocked=true
    • 其他情况,则调用abortBrokenDispatchCycleLocked
  • abortBrokenDispatchCycleLocked()方法最终会调用到Java层的IMS.notifyInputChannelBroken().

2.9 inputPublisher.publishKeyEvent

[-> InputTransport.cpp]

status_t InputPublisher::publishKeyEvent(...) {
    if (!seq) {
        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;
    //通过InputChannel来发送消息
    return mChannel->sendMessage(&msg);
}

InputChannel通过socket向远端的socket发送消息。socket通道是如何建立的呢? InputDispatcher又是如何与前台的window通信的呢? 见下一篇文章Input系统—进程交互, 从文章的小节2.1开始继续往下说.

2.10 releasePendingEventLocked

void InputDispatcher::releasePendingEventLocked() {
    if (mPendingEvent) {
        resetANRTimeoutsLocked(); //重置ANR超时时间
        releaseInboundEventLocked(mPendingEvent); //释放mPendingEvent对象,并记录到mRecentQueue队列
        mPendingEvent = NULL; //置空mPendingEvent变量.
    }
}

三. 处理Comand

3.1 runCommandsLockedInterruptible

bool InputDispatcher::runCommandsLockedInterruptible() {
    if (mCommandQueue.isEmpty()) {
        return false;
    }

    do {
        //从mCommandQueue队列的头部取出第一个元素
        CommandEntry* commandEntry = mCommandQueue.dequeueAtHead();

        Command command = commandEntry->command;
        //此处调用的命令隐式地包含'LockedInterruptible'
        (this->*command)(commandEntry);

        commandEntry->connection.clear();
        delete commandEntry;
    } while (! mCommandQueue.isEmpty());
    return true;
}

通过循环方式处理完mCommandQueue队列的所有命令,处理过程从mCommandQueue中取出CommandEntry.

typedef void (InputDispatcher::*Command)(CommandEntry* commandEntry);
struct CommandEntry : Link<CommandEntry> {
    CommandEntry(Command command);

    Command command;
    sp<Connection> connection;
    nsecs_t eventTime;
    KeyEntry* keyEntry;
    sp<InputApplicationHandle> inputApplicationHandle;
    sp<InputWindowHandle> inputWindowHandle;
    String8 reason;
    int32_t userActivityEventType;
    uint32_t seq;
    bool handled;
};

前面小节【2.4.1】添加的doPokeUserActivityLockedInterruptible命令. 接下来进入该方法:

3.2 doPokeUserActivityLockedInterruptible

[-> InputDispatcher]

void InputDispatcher::doPokeUserActivityLockedInterruptible(CommandEntry* commandEntry) {
    mLock.unlock();
    //【见小节4.3】
    mPolicy->pokeUserActivity(commandEntry->eventTime, commandEntry->userActivityEventType);

    mLock.lock();
}

3.3 pokeUserActivity

[-> com_android_server_input_InputManagerService.cpp]

void NativeInputManager::pokeUserActivity(nsecs_t eventTime, int32_t eventType) {
    //[见小节4.4]
    android_server_PowerManagerService_userActivity(eventTime, eventType);
}

3.4 android_server_PowerManagerService_userActivity

[-> com_android_server_power_PowerManagerService.cpp]

void android_server_PowerManagerService_userActivity(nsecs_t eventTime, int32_t eventType) {
    // Tell the power HAL when user activity occurs.
    if (gPowerModule && gPowerModule->powerHint) {
        gPowerModule->powerHint(gPowerModule, POWER_HINT_INTERACTION, NULL);
    }

    if (gPowerManagerServiceObj) {
        ...
        //[见小节4.5]
        env->CallVoidMethod(gPowerManagerServiceObj,
                gPowerManagerServiceClassInfo.userActivityFromNative,
                nanoseconds_to_milliseconds(eventTime), eventType, 0);
    }
}

3.5 PMS.userActivityFromNative

[-> PowerManagerService.java]

private void userActivityFromNative(long eventTime, int event, int flags) {
    userActivityInternal(eventTime, event, flags, Process.SYSTEM_UID);
}

private void userActivityInternal(long eventTime, int event, int flags, int uid) {
    synchronized (mLock) {
        if (userActivityNoUpdateLocked(eventTime, event, flags, uid)) {
            updatePowerStateLocked();
        }
    }
}

runCommandsLockedInterruptible是不断地从mCommandQueue队列取出命令,然后执行直到全部执行完成。 除了doPokeUserActivityLockedInterruptible,还有其他如下命令:

  • doNotifyANRLockedInterruptible
  • doInterceptKeyBeforeDispatchingLockedInterruptible
  • doDispatchCycleFinishedLockedInterruptible
  • doNotifyInputChannelBrokenLockedInterruptible
  • doNotifyConfigurationChangedInterruptible

四. 总结

4.1 流程图

点击查看大图:

input_dispatcher_seq

4.2 核心方法

用一张图来整体概况InputDispatcher线程的主要工作:

input_dispatcher

图解:

  1. dispatchOnceInnerLocked(): 从InputDispatcher的mInboundQueue队列,取出事件EventEntry。另外该方法开始执行的时间点(currentTime)便是后续事件dispatchEntry的分发时间(deliveryTime)
  2. dispatchKeyLocked():满足一定条件时会添加命令doInterceptKeyBeforeDispatchingLockedInterruptible;
  3. enqueueDispatchEntryLocked():生成事件DispatchEntry并加入connection的outbound队列
  4. startDispatchCycleLocked():从outboundQueue中取出事件DispatchEntry, 重新放入connection的waitQueue队列;
  5. InputChannel.sendMessage通过socket方式将消息发送给远程进程;
  6. runCommandsLockedInterruptible():通过循环遍历地方式,依次处理mCommandQueue队列中的所有命令。而mCommandQueue队列中的命令是通过postCommandLocked()方式向该队列添加的。

一. 概述

前面文章都是介绍了两个线程InputReader和InputDispatcher的工作过程。在InputDispatcher的过程讲到 调用InputChanel通过socket与远程进程通信,本文便展开讲解这个socket是如何建立的。

对于InputReader和InputDispatcher都是运行在system_server进程; 用户点击的界面往往可能是某一个app,而每个app一般地都运行在自己的进程,这里就涉及到跨进程通信,app进程是如何与system进程建立通信。

要解答这些问题,从Activity最基本的创建过程开始说起。我们都知道一般地Activity对应一个应用窗口, 每一个窗口对应一个ViewRootImpl。窗口是如何添加到Activity的,从Activity.onCreate()为起点讲解。

二. UI线程

总所周知,Activity的生命周期的回调方法都是运行在主线程,也称之为UI线程,所有UI相关的操作都需要运行在该线程。本文虽然是UI线程,但并非只介绍所有运行在UI线程的流程,文中还涉及binder thread。

2.1 onCreate

[-> Activity.java]

protected void onCreate(Bundle savedInstanceState) {
    super.onCreate(savedInstanceState);
    setContentView(R.layout.activity_account_bind);
    ...
}

Activity启动是由system进程控制:

  1. handleLaunchActivity():会调用Activity.onCreate(), 该方法内再调用setContentView(),经过AMS与WMS的各种交互,层层调用后,进入step2
  2. handleResumeActivity():会调用Activity.makeVisible(),该方法继续调用便会执行到WindowManagerImpl.addView(), 该方法内部再调用WindowManagerGlobal.addView(),

2.2 addView

[-> WindowManagerGlobal.java]

public void addView(View view, ViewGroup.LayoutParams params,
        Display display, Window parentWindow) {
    ...
    //[见小节2.3]
    ViewRootImpl root = new ViewRootImpl(view.getContext(), display);
    //[见小节2.3.3]
    root.setView(view, wparams, panelParentView);
    ...
}

2.3 ViewRootImpl

[-> ViewRootImpl.java]

public ViewRootImpl(Context context, Display display) {
    mContext = context;
    //获取IWindowSession的代理类【见小节2.3.1】
    mWindowSession = WindowManagerGlobal.getWindowSession();
    mDisplay = display;
    mThread = Thread.currentThread(); //主线程
    mWindow = new W(this);
    mChoreographer = Choreographer.getInstance();
    ...
}
2.3.1 getWindowSession

[-> WindowManagerGlobal.java]

public static IWindowSession getWindowSession() {
    synchronized (WindowManagerGlobal.class) {
        if (sWindowSession == null) {
            try {
                //获取IMS的代理类
                InputMethodManager imm = InputMethodManager.getInstance();
                //获取WMS的代理类
                IWindowManager windowManager = getWindowManagerService();
                //经过Binder调用,最终调用WMS[见小节2.3.2]
                sWindowSession = windowManager.openSession(
                        new IWindowSessionCallback.Stub() {...},
                        imm.getClient(), imm.getInputContext());
            } catch (RemoteException e) {
                ...
            }
        }
        return sWindowSession
    }
}
2.3.2 WMS.openSession
public IWindowSession openSession(IWindowSessionCallback callback, IInputMethodClient client,
        IInputContext inputContext) {
    //创建Session对象
    Session session = new Session(this, callback, client, inputContext);
    return session;
}

再次经过Binder将数据写回app进程,则获取的便是Session的代理对象。

2.3.3 setView

[-> ViewRootImpl.java]

public void setView(View view, WindowManager.LayoutParams attrs, View panelParentView) {
    synchronized (this) {
      ...
      if ((mWindowAttributes.inputFeatures
          & WindowManager.LayoutParams.INPUT_FEATURE_NO_INPUT_CHANNEL) == 0) {
          mInputChannel = new InputChannel(); //创建InputChannel对象
      }
      //通过Binder调用,进入system进程的Session[见小节2.4]
      res = mWindowSession.addToDisplay(mWindow, mSeq, mWindowAttributes,
                  getHostVisibility(), mDisplay.getDisplayId(),
                  mAttachInfo.mContentInsets, mAttachInfo.mStableInsets,
                  mAttachInfo.mOutsets, mInputChannel);
      ...
      if (mInputChannel != null) {
          if (mInputQueueCallback != null) {
              mInputQueue = new InputQueue();
              mInputQueueCallback.onInputQueueCreated(mInputQueue);
          }
          //创建WindowInputEventReceiver对象[见3.1]
          mInputEventReceiver = new WindowInputEventReceiver(mInputChannel,
                  Looper.myLooper());
      }
    }
}

该方法主要功能:

  1. 创建Java层的InputChannel对象mInputChannel
  2. 向WMS注册InputChannel信息,通过InputChannel.openInputChannelPair创建的socket pair,将其中的客户端赋值给mInputChannel.
  3. 创建WindowInputEventReceiver对象

跨进程调用,进入binder thread执行如下方法:

2.4 Session.addToDisplay

[-> Session.java]

final class Session extends IWindowSession.Stub implements IBinder.DeathRecipient {

    public int addToDisplay(IWindow window, int seq, WindowManager.LayoutParams attrs,
            int viewVisibility, int displayId, Rect outContentInsets, Rect outStableInsets,
            Rect outOutsets, InputChannel outInputChannel) {
        //[见小节2.5]
        return mService.addWindow(this, window, seq, attrs, viewVisibility, displayId,
                outContentInsets, outStableInsets, outOutsets, outInputChannel);
    }
}

2.5 WMS.addToDisplay

[-> WindowManagerService.java]

public int addWindow(Session session, IWindow client, int seq,
           WindowManager.LayoutParams attrs, int viewVisibility, int displayId,
           Rect outContentInsets, Rect outStableInsets, Rect outOutsets,
           InputChannel outInputChannel) {
    ...
    //创建WindowState【见小节2.5.1】
    WindowState win = new WindowState(this, session, client, token,
                attachedWindow, appOp[0], seq, attrs, viewVisibility, displayContent);
                
    if (outInputChannel != null && (attrs.inputFeatures
            & WindowManager.LayoutParams.INPUT_FEATURE_NO_INPUT_CHANNEL) == 0) {
         //根据WindowState的HashCode以及title来生成InputChannel名称
        String name = win.makeInputChannelName();
        
        //创建一对InputChannel[见小节2.6]
        InputChannel[] inputChannels = InputChannel.openInputChannelPair(name);
        //将socket服务端保存到WindowState的mInputChannel
        win.setInputChannel(inputChannels[0]);
        
        //socket客户端传递给outInputChannel [见小节2.7]
        inputChannels[1].transferTo(outInputChannel);
        //利用socket服务端作为参数[见小节2.8]
        mInputManager.registerInputChannel(win.mInputChannel, win.mInputWindowHandle);
    }
    ...
    boolean focusChanged = false;
    if (win.canReceiveKeys()) {
        //新添加window能接收按下操作,则更新聚焦窗口。
        focusChanged = updateFocusedWindowLocked(UPDATE_FOCUS_WILL_ASSIGN_LAYERS,
                false /*updateInputWindows*/);
    }
    ...
    
    if (focusChanged) {
        mInputMonitor.setInputFocusLw(mCurrentFocus, false /*updateInputWindows*/);
    }
    //设置当前聚焦窗口【见小节2.5.2】
    mInputMonitor.updateInputWindowsLw(false /*force*/);
}

inputChannels数组:

  • inputChannels[0]所对应的InputChannel名称的后缀为(server);
  • inputChannels[1]所对应的InputChannel名称的后缀为(client)

其中:

  • 服务端inputChannels[0]保存到WindowState的mInputChannel;
  • 客户端inputChannels[1]传递给outInputChannel,最终传递给ViewRootImpl的mInputChannel;
2.5.1 WindowState初始化

[-> WindowState.java]

WindowState(WindowManagerService service, Session s, IWindow c, WindowToken token,
       WindowState attachedWindow, int appOp, int seq, WindowManager.LayoutParams a,
       int viewVisibility, final DisplayContent displayContent) {
    ...
    WindowState appWin = this;
    while (appWin.mAttachedWindow != null) {
       appWin = appWin.mAttachedWindow;
    }
    WindowToken appToken = appWin.mToken;
    while (appToken.appWindowToken == null) {
       WindowToken parent = mService.mTokenMap.get(appToken.token);
       if (parent == null || appToken == parent) {
           break;
       }
       appToken = parent;
    }
    mAppToken = appToken.appWindowToken;
    //创建InputWindowHandle对象
    mInputWindowHandle = new InputWindowHandle(
            mAppToken != null ? mAppToken.mInputApplicationHandle : null, this,
            displayContent.getDisplayId());
}
2.5.2 updateInputWindowsLw

[-> InputMonitor.java]

public void updateInputWindowsLw(boolean force) {
    ...
    final InputWindowHandle dragWindowHandle = mService.mDragState.mDragWindowHandle;
    if (dragWindowHandle != null) {
        //将dragWindowHandle赋值给mInputWindowHandles
        addInputWindowHandleLw(dragWindowHandle);
    } 
    ...
    //将当前mInputWindowHandles传递到native【】
    mService.mInputManager.setInputWindows(mInputWindowHandles);
    ...
}

setInputWindows的调用链:(最终设置mFocusedWindowHandle值)

-> IMS.setInputWindows 
  -> NativeInputManager::setInputWindows
    -> InputDispatcher::setInputWindows

dragWindowHandle的初始化过程:

View.startDrag
    Session.prepareDrag
      WMS.prepareDragSurface
        mDragState = new DragState(...);
    Session.performDrag   
      DragState.register
        mDragWindowHandle = new InputWindowHandle(...);   

2.6 openInputChannelPair

[-> InputChannel.java]

public static InputChannel[] openInputChannelPair(String name) {
    return nativeOpenInputChannelPair(name);
}

这个过程的主要功能

  1. 创建两个socket通道(非阻塞, buffer上限32KB)
  2. 创建两个InputChannel对象;
  3. 创建两个NativeInputChannel对象;
  4. 将nativeInputChannel保存到Java层的InputChannel的成员变量mPtr
2.6.1 nativeOpenInputChannelPair

[-> android_view_InputChannel.cpp]

static jobjectArray android_view_InputChannel_nativeOpenInputChannelPair(JNIEnv* env,
        jclass clazz, jstring nameObj) {
    const char* nameChars = env->GetStringUTFChars(nameObj, NULL);
    String8 name(nameChars);
    env->ReleaseStringUTFChars(nameObj, nameChars);

    sp<InputChannel> serverChannel;
    sp<InputChannel> clientChannel;
    //创建一对socket[见小节2.6.2]
    status_t result = InputChannel::openInputChannelPair(name, serverChannel, clientChannel);

    //创建Java数组
    jobjectArray channelPair = env->NewObjectArray(2, gInputChannelClassInfo.clazz, NULL);
    ...

    //创建NativeInputChannel对象[见小节2.6.3]
    jobject serverChannelObj = android_view_InputChannel_createInputChannel(env,
            new NativeInputChannel(serverChannel));
    ...
    
    //创建NativeInputChannel对象[见小节2.6.3]
    jobject clientChannelObj = android_view_InputChannel_createInputChannel(env,
            new NativeInputChannel(clientChannel));
    ...
    
    //将client和server 两个插入到channelPair
    env->SetObjectArrayElement(channelPair, 0, serverChannelObj);
    env->SetObjectArrayElement(channelPair, 1, clientChannelObj);
    return channelPair;
}
2.6.2 openInputChannelPair

[-> InputTransport.cpp]

status_t InputChannel::openInputChannelPair(const String8& name,
        sp<InputChannel>& outServerChannel, sp<InputChannel>& outClientChannel) {
    int sockets[2];
    //真正创建socket对的地方【核心】
    if (socketpair(AF_UNIX, SOCK_SEQPACKET, 0, sockets)) {
        ...
        return result;
    }

    int bufferSize = SOCKET_BUFFER_SIZE; //32k
    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)");
    //创建InputChannel对象
    outServerChannel = new InputChannel(serverChannelName, sockets[0]);

    String8 clientChannelName = name;
    clientChannelName.append(" (client)");
    //创建InputChannel对象
    outClientChannel = new InputChannel(clientChannelName, sockets[1]);
    return OK;
}

该方法主要功能:

  1. 创建socket pair; (非阻塞式的socket)
  2. 设置两个socket的接收和发送的buffer上限为32KB;
  3. 创建client和server的Native层InputChannel对象;
    • sockets[0]所对应的InputChannel名称的后缀为(server);
    • sockets[1]所对应的InputChannel名称的后缀为(client)

创建InputChannel对象位于文件InputTransport.cpp,如下:

InputChannel::InputChannel(const String8& name, int fd) :
        mName(name), mFd(fd) {
    //将socket设置成非阻塞方式
    int result = fcntl(mFd, F_SETFL, O_NONBLOCK);
}

另外,创建NativeInputChannel对象位于文件android_view_InputChannel.cpp,如下:

NativeInputChannel::NativeInputChannel(const sp<InputChannel>& inputChannel) :
  mInputChannel(inputChannel), mDisposeCallback(NULL) {
}
2.6.3 android_view_InputChannel_createInputChannel

[-> android_view_InputChannel.cpp]

static jobject android_view_InputChannel_createInputChannel(JNIEnv* env,
        NativeInputChannel* nativeInputChannel) {
    //创建Java的InputChannel
    jobject inputChannelObj = env->NewObject(gInputChannelClassInfo.clazz,
            gInputChannelClassInfo.ctor);
    if (inputChannelObj) {
        //将nativeInputChannel保存到Java层的InputChannel的成员变量mPtr
        android_view_InputChannel_setNativeInputChannel(env, inputChannelObj, nativeInputChannel);
    }
    return inputChannelObj;
}

static void android_view_InputChannel_setNativeInputChannel(JNIEnv* env, jobject inputChannelObj,
        NativeInputChannel* nativeInputChannel) {
    env->SetLongField(inputChannelObj, gInputChannelClassInfo.mPtr,
             reinterpret_cast<jlong>(nativeInputChannel));
}

此处:

  • gInputChannelClassInfo.clazz是指Java层的InputChannel类
  • gInputChannelClassInfo.ctor是指Java层的InputChannel构造方法;
  • gInputChannelClassInfo.mPtr是指Java层的InputChannel的成员变量mPtr;

2.7 transferTo

[-> InputChannel.java]

public void transferTo(InputChannel outParameter) {    
    nativeTransferTo(outParameter);
}
2.7.1 nativeTransferTo

[-> android_view_InputChannel.cpp]

static void android_view_InputChannel_nativeTransferTo(JNIEnv* env, jobject obj,
        jobject otherObj) {
    
    if (android_view_InputChannel_getNativeInputChannel(env, otherObj) != NULL) {
        return; //当Java层的InputChannel.mPtr不为空,则返回
    }
    
    //将当前inputChannels[1]的mPtr赋值给nativeInputChannel
    NativeInputChannel* nativeInputChannel =
            android_view_InputChannel_getNativeInputChannel(env, obj);
    // 将该nativeInputChannel保存到outInputChannel的参数
    android_view_InputChannel_setNativeInputChannel(env, otherObj, nativeInputChannel);
    android_view_InputChannel_setNativeInputChannel(env, obj, NULL);
}

inputChannels[1].transferTo(outInputChannel)主要功能:

  1. 当outInputChannel.mPtr不为空,则直接返回;否则进入step2;
  2. 将inputChannels[1].mPtr的值赋给outInputChannel.mPtr;
  3. 清空inputChannels[1].mPtr值;

也就是将socket客户端inputChannels[1]传递给outInputChannel;

2.8 IMS.registerInputChannel

[-> InputManagerService.java]

public void registerInputChannel(InputChannel inputChannel,
        InputWindowHandle inputWindowHandle) {
    nativeRegisterInputChannel(mPtr, inputChannel, inputWindowHandle, false);
}
  • inputChannel是指inputChannels[0],即socket服务端;
  • inputWindowHandle是指WindowState.mInputWindowHandle;
2.8.1 nativeRegisterInputChannel

[-> com_android_server_input_InputManagerService.cpp]

static void nativeRegisterInputChannel(JNIEnv* env, jclass /* clazz */,
        jlong ptr, jobject inputChannelObj, jobject inputWindowHandleObj, jboolean monitor) {
    NativeInputManager* im = reinterpret_cast<NativeInputManager*>(ptr);

    sp<InputChannel> inputChannel = android_view_InputChannel_getInputChannel(env,
            inputChannelObj);

    sp<InputWindowHandle> inputWindowHandle =
            android_server_InputWindowHandle_getHandle(env, inputWindowHandleObj);
    
    //[见小节2.8.2]
    status_t status = im->registerInputChannel(
            env, inputChannel, inputWindowHandle, monitor);
    ...

    if (! monitor) {
        android_view_InputChannel_setDisposeCallback(env, inputChannelObj,
                handleInputChannelDisposed, im);
    }
}
2.8.2 registerInputChannel

[-> com_android_server_input_InputManagerService.cpp]

status_t NativeInputManager::registerInputChannel(JNIEnv* /* env */,
        const sp<InputChannel>& inputChannel,
        const sp<InputWindowHandle>& inputWindowHandle, bool monitor) {
    //[见小节2.8.3]
    return mInputManager->getDispatcher()->registerInputChannel(
            inputChannel, inputWindowHandle, monitor);
}

mInputManager是指NativeInputManager初始化过程创建的InputManager对象(C++).

2.8.3 registerInputChannel

[-> InputDispatcher.cpp]

status_t InputDispatcher::registerInputChannel(const sp<InputChannel>& inputChannel,
        const sp<InputWindowHandle>& inputWindowHandle, bool monitor) {
    { 
        AutoMutex _l(mLock);
        ...
        
        //创建Connection[见小节2.8.4]
        sp<Connection> connection = new Connection(inputChannel, inputWindowHandle, monitor);

        int fd = inputChannel->getFd();
        mConnectionsByFd.add(fd, connection);
        ...
        //将该fd添加到Looper监听[见小节2.8.5]
        mLooper->addFd(fd, 0, ALOOPER_EVENT_INPUT, handleReceiveCallback, this);
    }

    mLooper->wake(); //connection改变, 则唤醒looper
    return OK;
}

将新创建的connection保存到mConnectionsByFd成员变量,“InputDispatcher”线程的Looper添加对socket服务端的监听功能; 当该socket有消息时便会唤醒该线程工作。

2.8.4 初始化Connection

[-> InputDispatcher.cpp]

InputDispatcher::Connection::Connection(const sp<InputChannel>& inputChannel,
        const sp<InputWindowHandle>& inputWindowHandle, bool monitor) :
        status(STATUS_NORMAL), inputChannel(inputChannel), inputWindowHandle(inputWindowHandle),
        monitor(monitor),
        inputPublisher(inputChannel), inputPublisherBlocked(false) {
}

其中InputPublisher初始化位于文件InputTransport.cpp

InputPublisher:: InputPublisher(const sp<InputChannel>& channel) :
        mChannel(channel) {
}

此处inputChannel是指前面openInputChannelPair创建的socket服务端,将其同时保存到Connection.inputChannel和InputPublisher.mChannel。

2.8.5 Looper.addFd

[-> system/core/libutils/Looper.cpp]

int Looper::addFd(int fd, int ident, int events, Looper_callbackFunc callback, void* data) {
    // 此处的callback为handleReceiveCallback 
    return addFd(fd, ident, events, callback ? new SimpleLooperCallback(callback) : NULL, data);
}

int Looper::addFd(int fd, int ident, int events, const sp<LooperCallback>& callback, void* data) {
    {
        AutoMutex _l(mLock);
        Request request;
        request.fd = fd;
        request.ident = ident;
        request.events = events;
        request.seq = mNextRequestSeq++;
        request.callback = callback; //是指SimpleLooperCallback
        request.data = data;
        if (mNextRequestSeq == -1) mNextRequestSeq = 0;
        
        struct epoll_event eventItem;
        request.initEventItem(&eventItem);

        ssize_t requestIndex = mRequests.indexOfKey(fd);
        if (requestIndex < 0) {
            //通过epoll监听fd
            int epollResult = epoll_ctl(mEpollFd, EPOLL_CTL_ADD, fd, & eventItem);
            ...
            mRequests.add(fd, request); //该fd的request加入到mRequests队列
        } else {
            int epollResult = epoll_ctl(mEpollFd, EPOLL_CTL_MOD, fd, & eventItem);
            ...
            mRequests.replaceValueAt(requestIndex, request);
        }
    } 
    return 1;
}

此处Loop便是“InputDispatcher”线程的Looper,将socket服务端的fd采用epoll机制注册监听.

小节

虽然本文介绍的UI线程的工作,

  • [小节2.1 ~ 2.3]: 运行在UI线程;
  • [小节2.4 ~ 2.8]:通过IWindowSession的Binder IPC调用,运行在system_server的binder thread;

ViewRootImpl的setView()过程:

  • 创建socket pair,作为InputChannel:
    • socket服务端保存到system_server中的WindowState的mInputChannel;
    • socket客户端通过binder传回到远程进程的UI主线程ViewRootImpl的mInputChannel;
  • IMS.registerInputChannel()注册InputChannel,监听socket服务端:
    • Loop便是“InputDispatcher”线程的Looper;
    • 回调方法handleReceiveCallback。

三. WindowInputEventReceiver

接下来,看看【小节2.3.3】创建WindowInputEventReceiver对象

3.1 WindowInputEventReceiver初始化

[-> ViewRootImpl.java]

final class WindowInputEventReceiver extends InputEventReceiver {
    //inputChannel是指socket客户端,Looper是指UI线程的Looper
    public WindowInputEventReceiver(InputChannel inputChannel, Looper looper) {
        super(inputChannel, looper); //【见小节3.2】
    }
    ...
}

3.2 InputEventReceiver

[-> InputEventReceiver.java]

public InputEventReceiver(InputChannel inputChannel, Looper looper) {
     ...
     mInputChannel = inputChannel;
     mMessageQueue = looper.getQueue(); //UI线程消息队列
     //【加小节3.3】
     mReceiverPtr = nativeInit(new WeakReference<InputEventReceiver>(this),
             inputChannel, mMessageQueue);
 }

3.3 nativeInit

[-> android_view_InputEventReceiver.cpp]

static jlong nativeInit(JNIEnv* env, jclass clazz, jobject receiverWeak,
        jobject inputChannelObj, jobject messageQueueObj) {
    sp<InputChannel> inputChannel = android_view_InputChannel_getInputChannel(env,
            inputChannelObj);
    //获取UI主线程的消息队列
    sp<MessageQueue> messageQueue = android_os_MessageQueue_getMessageQueue(env, messageQueueObj);
    //创建NativeInputEventReceiver对象【见小节3.4】
    sp<NativeInputEventReceiver> receiver = new NativeInputEventReceiver(env,
            receiverWeak, inputChannel, messageQueue);
    //【见小节3.5】
    status_t status = receiver->initialize();
    ...

    receiver->incStrong(gInputEventReceiverClassInfo.clazz); 
    return reinterpret_cast<jlong>(receiver.get());
}

3.4 NativeInputEventReceiver

[-> android_view_InputEventReceiver.cpp]

class NativeInputEventReceiver : public LooperCallback {
    InputConsumer mInputConsumer;
    sp<MessageQueue> mMessageQueue;
    int mFdEvents;
    bool mBatchedInputEventPending;
    ...
    
    NativeInputEventReceiver::NativeInputEventReceiver(JNIEnv* env,
            jobject receiverWeak, const sp<InputChannel>& inputChannel,
            const sp<MessageQueue>& messageQueue) :
            mReceiverWeakGlobal(env->NewGlobalRef(receiverWeak)),
            //【见3.4.1】
            mInputConsumer(inputChannel), mMessageQueue(messageQueue),
            mBatchedInputEventPending(false), mFdEvents(0) {
            
    }
}
3.4.1 InputConsumer

[-> InputTransport.cpp]

InputConsumer::InputConsumer(const sp<InputChannel>& channel) :
        mResampleTouch(isTouchResamplingEnabled()),
        mChannel(channel), mMsgDeferred(false) {
}

此处inputChannel是指socket客户端。

3.5 initialize

[-> android_view_InputEventReceiver.cpp]

status_t NativeInputEventReceiver::initialize() {
    setFdEvents(ALOOPER_EVENT_INPUT);  //【见小节3.6】
    return OK;
}

3.6 setFdEvents

[-> android_view_InputEventReceiver.cpp]

void NativeInputEventReceiver::setFdEvents(int events) {
  if (mFdEvents != events) {
      mFdEvents = events;
      int fd = mInputConsumer.getChannel()->getFd();
      if (events) {
          //将socket客户端的fd添加到主线程的消息池【见小节3.6.1】
          mMessageQueue->getLooper()->addFd(fd, 0, events, this, NULL);
      } else {
          mMessageQueue->getLooper()->removeFd(fd);
      }
  }
}    
3.6.1 Looper.addFd

[-> system/core/libutils/Looper.cpp]

int Looper::addFd(int fd, int ident, int events, const sp<LooperCallback>& callback, void* data) {
    {
        AutoMutex _l(mLock);
        Request request;
        request.fd = fd;
        request.ident = ident;
        request.events = events;
        request.seq = mNextRequestSeq++;
        request.callback = callback; //是指ativeInputEventReceiver
        request.data = data;
        if (mNextRequestSeq == -1) mNextRequestSeq = 0;
        
        struct epoll_event eventItem;
        request.initEventItem(&eventItem);

        ssize_t requestIndex = mRequests.indexOfKey(fd);
        if (requestIndex < 0) {
            //通过epoll监听fd
            int epollResult = epoll_ctl(mEpollFd, EPOLL_CTL_ADD, fd, & eventItem);
            ...
            mRequests.add(fd, request); //该fd的request加入到mRequests队列
        } else {
            int epollResult = epoll_ctl(mEpollFd, EPOLL_CTL_MOD, fd, & eventItem);
            ...
            mRequests.replaceValueAt(requestIndex, request);
        }
    } 
    return 1;
}

此处的Looper便是UI主线程的Looper,将socket客户端的fd添加到UI线程的Looper来监听,回调方法为NativeInputEventReceiver。

四. 总结

input_ui

首先,通过openInputChannelPair来创建socket pair,作为InputChannel:

  • socket服务端保存到system_server中的WindowState的mInputChannel;
  • socket客户端通过binder传回到远程进程的UI主线程ViewRootImpl的mInputChannel;

紧接着,完成了两个线程的epoll监听工作:

  • [小节2.8]IMS.registerInputChannel(): “InputDispatcher”线程监听socket服务端,收到消息后回调InputDispatcher.handleReceiveCallback();
  • [小节3.6]setFdEvents(): UI主线程监听socket客户端,收到消息后回调NativeInputEventReceiver.handleEvent().

有了这些“InputDispatcher”和“UI”主线程便可以进行跨进程通信与交互。


  • 1
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 2
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值