您当前的位置: 首页 > 
  • 2浏览

    0关注

    417博文

    0收益

  • 0浏览

    0点赞

    0打赏

    0留言

私信
关注
热门博文

06.输入系统:第10课第7节_输入系统_Reader线程_简单处理

江南才尽,年少无知! 发布时间:2019-03-08 17:28:57 ,浏览量:2

在前面的小节中,我们对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。

关注
打赏
1592542134
查看更多评论
立即登录/注册

微信扫码登录

0.0391s