首页 > 代码库 > Android按键事件发布流程

Android按键事件发布流程

总结一下,Android按键事件发布流程

//InputReader.cpp
void InputReader::loopOnce() {
     ...
     size_t count = mEventHub->getEvents(timeoutMillis, mEventBuffer, EVENT_BUFFER_SIZE);

     if (count) {
        processEventsLocked(mEventBuffer, count);
     }
     ...
 }
InputReader线程启动后,循环调用loopOnce,loopOnce调用mEventHub的getEvents函数,有事件返回底层事件数count,没有则休眠。

//InputReader.cpp
void InputReader::processEventsLocked(const RawEvent* rawEvents, size_t count) {
     ...
     processEventsForDeviceLocked(deviceId, rawEvent, batchSize);

     ...
}
随后调动上述方法,把事件发送给指定设备。

//InputReader.cpp
void InputReader::processEventsForDeviceLocked(int32_t deviceId,
        const RawEvent* rawEvents, size_t count) {
      ...
      device->process(rawEvents, count);
      ...
} 
设备处理该事件

//InputReader.cpp
void InputDevice::process(const RawEvent* rawEvents, size_t count) {
    ...
    mapper->process(rawEvent);
    ...
}

每个设备可能有多种mapper,比如既有按键又有触摸板,把事件发给相应的mapper

//InputReader.cpp
void KeyboardInputMapper::process(const RawEvent* rawEvent) {
    ...
    processKey(rawEvent->when, rawEvent->value != 0, keyCode, scanCode, flags);
    ...

}

键盘mapper处理事件

//InputReader.cpp
void KeyboardInputMapper::processKey(nsecs_t when, bool down, int32_t keyCode,
        int32_t scanCode, uint32_t policyFlags) {
    ...
    getListener()->notifyKey(&args);
    ...

}
调用InputDispatcher的notifyKey函数。

//InputDispatcher.cpp
void InputDispatcher::notifyKey(const NotifyKeyArgs* args) {
    ....
    needWake = enqueueInboundEventLocked(newEntry);
    if(needWake){
     mLooper->wake();
    }
 }
notify函数,将事件加入inputDispatcher的 inbound队列,此时应需要选择是否唤醒inputDispatcher线程

//InputDispatcher.cpp
bool InputDispatcher::enqueueInboundEventLocked(EventEntry* entry) {
    bool needWake = mInboundQueue.isEmpty();
    mInboundQueue.enqueueAtTail(entry);
    ....
    return needWake;
}


//InputDispatcher.cpp
void InputDispatcher::dispatchOnce(){
  ...
   dispatchOnceInnerLocked(&nextWakeupTime);
  ...
   mLooper->pollOnce(timeoutMillis);
}
唤醒后,inputdispatcher线程,继续执行dispatchOnce函数,如果没有事件,则休眠在looper的pollOnce函数。

//InputDispatcher.cpp
void InputDispatcher::dispatchOnceInnerLocked(nsecs_t* nextWakeupTime) {
     ...
     dispatchKeyLocked(currentTime, typedEntry, &dropReason, nextWakeupTime);
     ...
 }

如果有事件发生,则发布。

//InputDispatcher.cpp
bool InputDispatcher::dispatchKeyLocked(nsecs_t currentTime, KeyEntry* entry,
        DropReason* dropReason, nsecs_t* nextWakeupTime) {

     ...
     int32_t injectionResult = findFocusedWindowTargetsLocked(currentTime,
            entry, inputTargets, nextWakeupTime);


     dispatchEventLocked(currentTime, entry, inputTargets);
     ...
} 

首先寻找获得焦点的窗口,并将事件发送给它

//InputDispatcher.cpp
void InputDispatcher::dispatchEventLocked(nsecs_t currentTime,
        EventEntry* eventEntry, const Vector<InputTarget>& inputTargets) {
      ...
    for (size_t i = 0; i < inputTargets.size(); i++) {
        const InputTarget& inputTarget = inputTargets.itemAt(i);
        ssize_t connectionIndex = getConnectionIndexLocked(inputTarget.inputChannel);
        if (connectionIndex >= 0) {
            sp<Connection> connection = mConnectionsByFd.valueAt(connectionIndex);
            prepareDispatchCycleLocked(currentTime, connection, eventEntry, &inputTarget);
        } 
       ...
    }
}

//InputDispatcher.cpp
void InputDispatcher::prepareDispatchCycleLocked(nsecs_t currentTime,
        const sp<Connection>& connection, EventEntry* eventEntry, const InputTarget* inputTarget){
   ...
   enqueueDispatchEntriesLocked(currentTime, connection,
                    splitMotionEntry, inputTarget);
   ...
 }



//InputDispathcer.cpp
void InputDispatcher::enqueueDispatchEntriesLocked(nsecs_t currentTime,
        const sp<Connection>& connection, EventEntry* eventEntry, const InputTarget* inputTarget) {
    ...
    startDispatchCycleLocked(currentTime, connection);
    ...

}
将事件加入到outbound队列,准备发送到app
//InputDispatcher.cpp
void InputDispatcher::startDispatchCycleLocked(nsecs_t currentTime,
        const sp<Connection>& connection){
      ...
      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);

      ...

}


//InputTransport.cpp
status_t InputPublisher::publishKeyEvent(
        uint32_t seq,
        int32_t deviceId,
        int32_t source,
        int32_t action,
        int32_t flags,
        int32_t keyCode,
        int32_t scanCode,
        int32_t metaState,
        int32_t repeatCount,
        nsecs_t downTime,
        nsecs_t eventTime) {

    ...
    return mChannel->sendMessage(&msg);
} 
通过通道,发送事件消息
//InputTransport.cpp
status_t InputChannel::sendMessage(const InputMessage* msg) {
    size_t msgLength = msg->size();
    ssize_t nWrite;
    do {
        nWrite = ::send(mFd, msg, msgLength, MSG_DONTWAIT | MSG_NOSIGNAL);
     ...
}


//Looper.cpp
int Looper::pollInner(int timeoutMillis) {
    struct epoll_event eventItems[EPOLL_MAX_EVENTS];
    //等待消息
    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 == ALOOPER_POLL_CALLBACK) {
            int fd = response.request.fd;
            int events = response.events;
            void* data = http://www.mamicode.com/response.request.data;>app looper会监测channel下socket fd,当fd发生变化,回调当时注册的函数NativeInputEventReciever
//android_view_InputEventReceiver.cpp
int NativeInputEventReceiver::handleEvent(int receiveFd, int events, void* data) {
   ...
    status_t status = consumeEvents(env, false /*consumeBatches*/, -1, NULL);
   ...

}

//android_view_InputEventReceiver.cppstatus_t NativeInputEventReceiver::consumeEvents(JNIEnv* env, bool consumeBatches, nsecs_t frameTime, bool* outConsumedBatch) {....  status_t status = mInputConsumer.consume(&mInputEventFactory,                consumeBatches, frameTime, &seq, &inputEvent);...env->CallVoidMethod(receiverObj.get(),                        gInputEventReceiverClassInfo.dispatchInputEvent, seq, inputEventObj);...}

通过jni调用java函数,dispatchInputevent
//InputTransport.cpp
status_t InputConsumer::consume(InputEventFactoryInterface* factory,
        bool consumeBatches, nsecs_t frameTime, uint32_t* outSeq, InputEvent** outEvent) {
        ...
            status_t result = mChannel->receiveMessage(&mMsg);
        ...
}
//通过通道收取消息,初始化按键事件

 //InputEventReceiver.java
// Called from native code.
    @SuppressWarnings("unused")
    private void dispatchInputEvent(int seq, InputEvent event) {
        mSeqMap.put(event.getSequenceNumber(), seq);
        onInputEvent(event);
    }
 此处onInputEent调用重写的子类方法。即WindowInputEventReceiver的方法

//ViewRootImpl.java
final class WindowInputEventReceiver extends InputEventReceiver {
        public WindowInputEventReceiver(InputChannel inputChannel, Looper looper) {
            super(inputChannel, looper);
        }

        @Override
        public void onInputEvent(InputEvent event) {
            enqueueInputEvent(event, this, 0, true);
        }


//ViewRootImpl.java 
void enqueueInputEvent(InputEvent event,
            InputEventReceiver receiver, int flags, boolean processImmediately) {
        QueuedInputEvent q = obtainQueuedInputEvent(event, receiver, flags);

        ...
        if (processImmediately) {
            doProcessInputEvents();
        } else {
            scheduleProcessInputEvents();
        }
    }




Android按键事件发布流程