在前面的小节中,我们对Reader线程做了总结,任务他会做三件事件。
1.获取事件
2.简单处理
3.传送给Dispather线程。
我们已经分析1.Reader线程怎么获取事件,这小节我们来讲解他是如何处理这些事件的,在Reader线程中,他只是做了简单的处理,复杂的处理是在Dispather线程中完成的。
我们先来猜测一下Reader线程会做哪些事情,会获取哪些输入事件。通过前面小节的讲解,知道Reader线程从驱动获取事件之后,会转换为RawEvent,提供给android系统使用。 其中type:有DEVICE_ADDED(插入设备),DEVICE_REMOVE(拔出设备),以及具体的输入事件,如按下按键,移动鼠标,触摸屏幕等等。可以看出,他们后续的处理中,都是根据type不同,进行不同的处理,简单分支图如下:
我们打开文件,inputReader.cpp搜索processEventsLocked,看看该函数在哪里被调用:
size_t count = mEventHub->getEvents(timeoutMillis, mEventBuffer, EVENT_BUFFER_SIZE);
{ // acquire lock
AutoMutex _l(mLock);
mReaderIsAliveCondition.broadcast();
if (count) {
processEventsLocked(mEventBuffer, count);
}
可以看到,在调用mEventHub->getEvents(timeoutMillis, mEventBuffer, EVENT_BUFFER_SIZE)之后,接着就调用了processEventsLocked(mEventBuffer, count),他们处于InputReader::loopOnce() 这个主循环之中。进入processEventsLocked方法。
InputReader::processEventsLocked(const RawEvent* rawEvents, size_t count) {
for (const RawEvent* rawEvent = rawEvents; count;) {//对于每一个RawEvent都进行相应的处理。
if (type when, rawEvent->deviceId);
InputDevice* device = createDeviceLocked() //根据插入的设备类型,创建相应的InputDevice
......
if (keyboardSource != 0) {
device->addMapper(new KeyboardInputMapper(device, keyboardSource, keyboardType));
......
mDevices.add(deviceId, device);//添加到KeyedVector mDevices中进行监测,用于管理多个输入设备
}
case EventHubInterface::DEVICE_REMOVED:
case EventHubInterface::FINISHED_DEVICE_SCAN:
大家可能觉得奇怪,在前面EventHub中InputReader::loopOnce() 分析以及对设备进行了添加,为什么这里还要在InputDevice调用mDevices.add(deviceId, device;再添加一次?这里是利用了分层的思想:
首先回顾一下EventHub中的mDevices,其中包含呢多个Device,关系与成员框图如下: 在InputReader中同样存在mDevices,mDevices中有多个InputDevice,每个InputDevice中都存在: 成员int32_t mId:在后续,根据每个InputDevice中的int32_t mId就能找到在EventHub.mDevices中的Device, 成员Vector mMappers:对上报的事件,用mMappers进行处理(稍后讲解)。
总结框图如下: 从图可以看出在InputReader层次的InputDevice负责处理事件,不用去关心fd,identifer等等,而EvenHub中的Device负责读取事件,这样分工与层次都比较明显。
我们回过头mMappers中包含了那些东西,假如我们的是键盘:
InputReader::addDeviceLocked(nsecs_t when, int32_t deviceId) {
device = createDeviceLocked(deviceId, controllerNumber, identifier, classes);
device->addMapper(new KeyboardInputMapper(device, keyboardSource, keyboardType));
mMappers.add(mapper);
对于键盘。存在一个KeyboardInputMapper对象,当输入事件是添加设备时,对其的分析就结束了。移除设备也是类似的原理。现在我们看看,真正的输入事件是如何处理的。把执行函数调用过程,复制一部分,添加相关调用过程:
InputReader::processEventsLocked(const RawEvent* rawEvents, size_t count) {
for (const RawEvent* rawEvent = rawEvents; count;) {//对于每一个RawEvent都进行相应的处理。
if (type process(rawEvents, count);//此处的device为之前构造的InputDevice
for (size_t i = 0; i process(rawEvent);//该处对于键盘,执行的是KeyboardInputMapper.process(rawEvent)。
case EV_KEY: {
processKey(rawEvent->when, rawEvent->value != 0, scanCode, usageCode);//根据kl或者kcm文件把驱动获得的按键码转换为android的按键码
/*根据是否按下shfit,按下的时间是否相同构建一个args*/
NotifyKeyArgs args(when, getDeviceId(), mSource, policyFlags,down ? AKEY_EVENT_ACTION_DOWN : AKEY_EVENT_ACTION_UP,AKEY_EVENT_FLAG_FROM_SYSTEM, keyCode, scanCode, keyMetaState,downTime);
/*通知一个Listener对args进行处理*/
getListener()->notifyKey(&args);
到了最后可以看到,调用getListener()->notifyKey(&args); 通知监测者处理按下的按键,那么这个监听者就是Reader_Dispatche线程(下一小节的内容)
从这里我们可以看出,Reader线程,对输入事件的处理是十分简单的,他仅仅是把从驱动获取的输入事件的scancode转化为android事件的code。