大家好,今天为大家推荐来自MIUI的Cheeeelok同学的AOSP源码分析系列文章,本文依然从源码的角度带大家理解Android Input事件的产生、读取和分发。还没有看过作者上一篇文章 Android Input子系统:Input进程的创建,监听线程的启动 的同学,现在补上同样不迟,好了,话不多说,直接进入正文。
在上一篇博文中学习了Android Input系统事件监听模块,我们了解到InputManagerService启动后会启动InputReader开始监听来自EventHub的事件。今天就沿着前文的思路,看看EventHub将事件交给InputReader后会发生什么。
本文的内容可以由下图概括:
Input事件的读取者InputReader
在上一篇博文中已经讲到,对于InputRead,它在监听过程中会做以下事情:
-
启动后循环执行mReader->loopOnce()
-
loopOnce()中会调用mEventHub->getEvents读取事件
-
读到了事件就会调用processEventsLocked处理事件
-
处理完成后调用getInputDevicesLocked获取输入设备信息
-
调用mPolicy->notifyInputDevicesChanged函数利用InputManagerService的代理通过Handler发送MSG_DELIVER_INPUT_DEVICES_CHANGED消息,通知输入设备发生了变化
-
最后调用mQueuedListener->flush(),将事件队列中的所有事件交给在InputReader中注册过的InputDispatcher
bool InputReaderThread::threadLoop() {
mReader->loopOnce();
return true;
}
void InputReader::loopOnce() {
……
size_t count = mEventHub->getEvents(timeoutMillis, mEventBuffer, EVENT_BUFFER_SIZE);
{ // acquire lock
AutoMutex _l(mLock);
mReaderIsAliveCondition.broadcast();
if (count) {
processEventsLocked(mEventBuffer, count);
}
…… if (oldGeneration != mGeneration) {
inputDevicesChanged = true;
getInputDevicesLocked(inputDevices);
}
} // release lock
// Send out a message that the describes the changed input devices.
if (inputDevicesChanged) {
mPolicy->notifyInputDevicesChanged(inputDevices);
}
……
mQueuedListener->flush();
}
接下来我们就学习它具体的处理流程吧。
processEventsLocked对Input事件进行处理、归类
在processEventsLocked函数中,它主要做了以下事情:
-
循环获取RawEvent
-
如果RawEvent->type小于FIRST_SYNTHETIC_EVENT,说明这是个来自kernel的Input事件,则调用processEventsForDeviceLocked函数处理
-
否则此时的RawEvent->type就代表着Input设备的增、删、扫描事件,则调用对应的设备处理函数进行处理
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) {
……
processEventsForDeviceLocked(deviceId, rawEvent, batchSize);
} else {
switch (rawEvent->type) {
case EventHubInterface::DEVICE_ADDED:
addDeviceLocked(rawEvent->when, rawEvent->deviceId);
break;
case EventHubInterface::DEVICE_REMOVED:
removeDeviceLocked(rawEvent->when, rawEvent->deviceId);
break;
case EventHubInterface::FINISHED_DEVICE_SCAN:
handleConfigurationChangedLocked(rawEvent->when);
break;
default:
ALOG_ASSERT(false); // can't happen
break;
}