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

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

//InputReader.cppvoid InputReader::processEventsLocked(const RawEvent* rawEvents, size_t count) {     ...     processEventsForDeviceLocked(deviceId, rawEvent, batchSize);     ...}
随后调动上述方法,把事件发送给指定设备。

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

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

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

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

键盘mapper处理事件

//InputReader.cppvoid KeyboardInputMapper::processKey(nsecs_t when, bool down, int32_t keyCode,        int32_t scanCode, uint32_t policyFlags) {    ...    getListener()->notifyKey(&args);    ...}
调用InputDispatcher的notifyKey函数。

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

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


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

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

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

//InputDispatcher.cppbool 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.cppvoid 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.cppvoid InputDispatcher::prepareDispatchCycleLocked(nsecs_t currentTime,        const sp<Connection>& connection, EventEntry* eventEntry, const InputTarget* inputTarget){   ...   enqueueDispatchEntriesLocked(currentTime, connection, splitMotionEntry, inputTarget);   ...}

接下来,将inboundqueue放入outboundqueue,开启发布循环

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

生产者,inputpulisher发送事件

//InputTransport.cppstatus_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.cppstatus_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.cppint 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 = response.request.data;            // callback--------NativeInputEventRecieverd            int callbackResult = response.request.callback->handleEvent(fd, events, data);            if (callbackResult == 0) {                removeFd(fd);            }            response.request.callback.clear();            result = ALOOPER_POLL_CALLBACK;        }    }    return result;}
app looper会监测channel下socket fd,当fd发生变化,回调当时注册的函数NativeInputEventReciever
//android_view_InputEventReceiver.cppint 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.cppstatus_t InputConsumer::consume(InputEventFactoryInterface* factory,        bool consumeBatches, nsecs_t frameTime, uint32_t* outSeq, InputEvent** outEvent) {        ...            status_t result = mChannel->receiveMessage(&mMsg);        ...}
inputconsuer消费者通过通道收取消息,初始化按键事件, 生产者运行于framework dispatch线程,消费者运行于app 主线程

 //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.javafinal 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();        }    }



转载请表明出处,谢谢

更多相关文章

  1. C语言函数以及函数的使用
  2. android字体闪烁动画(线程)
  3. 多线程实现更新android进度条。
  4. Android 按钮添加单击事件
  5. 《android的事件分发机制》
  6. android各种触摸事件的处理,touchEvent
  7. Android 线程池管理
  8. Android 音量增加减少按钮事件
  9. [Android]手动触发OnClick事件

随机推荐

  1. android 应用开发框架
  2. Android开发前景展望
  3. [置顶] 小巫的Android视频教学出来啦,欢迎
  4. 5分钟将OSC Android源码从Eclipse项目转
  5. 谈谈怎么最快学好android
  6. 零打碎敲学Android(二)—做个拼图游戏吧
  7. Android 文件管理方法
  8. Android中为TextView增加自定义的HTML标
  9. 编写高效的android代码(译文)
  10. Android 应用程序基础(Application Fundam