首页 > 代码库 > 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按键事件发布流程
声明:以上内容来自用户投稿及互联网公开渠道收集整理发布,本网站不拥有所有权,未作人工编辑处理,也不承担相关法律责任,若内容有误或涉及侵权可进行投诉: 投诉/举报 工作人员会在5个工作日内联系你,一经查实,本站将立刻删除涉嫌侵权内容。