Android系统--输入系统(八)Reader线程_使用EventHub读取事件
Android系统--输入系统(八)Reader线程_使用EventHub读取事件
1. Reader线程工作流程
- 获得事件
size_t count = mEventHub->getEvents(timeoutMillis, mEventBuffer, EVENT_BUFFER_SIZE);
- 简单处理
processEventsLocked(mEventBuffer, count);
- 将事件分发给Dispatch线程处理
mQueuedListener->flush();
2. Reader线程获得事件分析
2.1 事件结构体描述
struct RawEvent {
nsecs_t when;
int32_t deviceId;
int32_t type;
int32_t code;
int32_t value;
};
2.2 事件类型
事件类型type:
DEVICE_ADDED(输入设备插入)
DEVICE_REMOVED(输入设备被拔出)
FINISHED_DEVICE_SCAN(与Device相关的事件)
EV_KEY
EV_ABS
EV_REL
2.3 驱动层上报输入事件
struct input_event{
struct timeval time;
__u16 type;
__u16 code;
__s32 value;
};
上报事件类型Type:
EV_KEY
EV_ABS
EV_REL
2.4 驱动层上报输入事件给上层概述
当输入设备有数据产生,驱动程序将该事件数据上报,上层的Reader线程将读取驱动程序,获得Input_event结构体,然后将Input_event结构体直接构造成RawEvent结构体进行处理。
3. 输入设备拔插检测实现
3.1 实现原理
使用inotify机制来检测目录下的文件变化
使用epoll机制来检测目录下的文件是否有数据
3.2 实现过程分析
初始化得到文件句柄--fd1 = inotify_init(/dev/input/event0);
检测对象--inotify_add_watch(fd1,目录/文件,创建/删除);
将输入事件加入epoll池中,监听事件行为--add_to_epoll(mINotifyFd, mEpollFd);
由EventHub构造函数实现
EventHub.cpp
EventHub::EventHub(void) :
mEpollFd = epoll_create(EPOLL_SIZE_HINT);
LOG_ALWAYS_FATAL_IF(mEpollFd < 0, "Could not create epoll instance. errno=%d", errno);
mINotifyFd = inotify_init();
int result = inotify_add_watch(mINotifyFd, DEVICE_PATH, IN_DELETE | IN_CREATE);
LOG_ALWAYS_FATAL_IF(result < 0, "Could not register INotify for %s. errno=%d",
DEVICE_PATH, errno);
struct epoll_event eventItem;
memset(&eventItem, 0, sizeof(eventItem));
eventItem.events = EPOLLIN;
eventItem.data.u32 = EPOLL_ID_INOTIFY;
result = epoll_ctl(mEpollFd, EPOLL_CTL_ADD, mINotifyFd, &eventItem);
int wakeFds[2];
result = pipe(wakeFds);
mWakeReadPipeFd = wakeFds[0];
mWakeWritePipeFd = wakeFds[1];
result = fcntl(mWakeReadPipeFd, F_SETFL, O_NONBLOCK);
result = fcntl(mWakeWritePipeFd, F_SETFL, O_NONBLOCK);
eventItem.data.u32 = EPOLL_ID_WAKE;
result = epoll_ctl(mEpollFd, EPOLL_CTL_ADD, mWakeReadPipeFd, &eventItem);
}
在ScanDeviceLocked()函数中,实现对设备函数的打开
fd2 = open("/dev/input/event1");
fd3 = open("/dev/input/event2");
使用epoll_wait检测fd1,fd2,fd3
读取文件句柄,构造RawEvent结构体;getEvent的循环
如果是增加输入设备,还需要open,并将其加入epoll_wait
如果是拔出输入设备,从epoll中删去
if (eventItem.data.u32 == EPOLL_ID_INOTIFY) {
if (eventItem.events & EPOLLIN) {
mPendingINotify = true;
}
readNotifyLocked.c
status_t EventHub::readNotifyLocked() {
res = read(mINotifyFd, event_buf, sizeof(event_buf));
while(res >= (int)sizeof(*event)) {
event = (struct inotify_event *)(event_buf + event_pos);
//printf("%d: %08x \"%s\"\n", event->wd, event->mask, event->len ? event->name : "");
if(event->len) {
strcpy(filename, event->name);
if(event->mask & IN_CREATE) {
openDeviceLocked(devname);
} else {
ALOGI("Removing device '%s' due to inotify event\n", devname);
closeDeviceByPathLocked(devname);
}
}
event_size = sizeof(*event) + event->len;
res -= event_size;
event_pos += event_size;
}
return 0;
}
- 如果是输入设备有数据,读取Input_event
size_t deviceIndex = mDevices.indexOfKey(eventItem.data.u32);
if (deviceIndex < 0) {
ALOGW("Received unexpected epoll event 0x%08x for unknown device id %d.",
eventItem.events, eventItem.data.u32);
continue;
}
Device* device = mDevices.valueAt(deviceIndex);
if (eventItem.events & EPOLLIN) {
int32_t readSize = read(device->fd, readBuffer,
sizeof(struct input_event) * capacity);
}
- 将input_event结构体构造为RawEvent结构体
event->deviceId = deviceId;
event->type = iev.type;
event->code = iev.code;
event->value = iev.value;
4. 使用EventHub读取事件概述

Android系统--输入系统(八)Reader线程_使用EventHub读取事件的更多相关文章
- 10.5 android输入系统_Reader线程_使用EventHub读取事件和核心类及配置文件_实验_分析
4. Reader线程_使用EventHub读取事件 使用inotify监测/dev/input下文件的创建和删除 使用epoll监测有无数据上报 细节: a.fd1 = inotify_init(& ...
- Android系统--输入系统(九)Reader线程_核心类及配置文件
Android系统--输入系统(九)Reader线程_核心类及配置文件 1. Reader线程核心类--EventHub 1.1 Reader线程核心结构体 实例化对象:mEventHub--表示多个 ...
- Android系统--输入系统(十)Reader线程_核心类及配置文件深入分析
Android系统--输入系统(十)Reader线程_核心类及配置文件深入分析 0. 前言 个人认为该知识点阅读Android源代码会不仅容易走进死胡同,并且效果并不好,前脚看完后脚忘记,故进行总结, ...
- Android系统--输入系统(十一)Reader线程_简单处理
Android系统--输入系统(十一)Reader线程_简单处理 1. 引入 Reader线程主要负责三件事情 获得输入事件 简单处理 上传给Dispatch线程 InputReader.cpp vo ...
- Android系统--输入系统(十二)Dispatch线程_总体框架
Android系统--输入系统(十二)Dispatch线程_总体框架 1. Dispatch线程框架 我们知道Dispatch线程是分发之意,那么便可以引入两个问题:1. 发什么;2. 发给谁.这两个 ...
- Android系统--输入系统(十七)Dispatcher线程_分发dispatch
Android系统--输入系统(十七)Dispatcher线程_分发dispatch 1. 回顾 InputRead线程从输入设备当中得到输入事件 对于读到输入事件稍作处理,比如紧急事件,来电时候按下 ...
- Android系统--输入系统(七)Reader_Dispatcher线程启动分析
Android系统--输入系统(七)Reader_Dispatcher线程启动分析 1. Reader/Dispatcher的引入 对于输入系统来说,将会创建两个线程: Reader线程(读取事件) ...
- Android系统--输入系统(十三)Dispatcher线程情景分析_Reader线程传递事件
Android系统--输入系统(十三)Dispatcher线程情景分析_Reader线程传递事件 1. 输入按键 我们知道Android系统的按键分为三类:(1)Global Key;(2)Syste ...
- Android系统--输入系统(十四)Dispatcher线程情景分析_dispatch前处理
Android系统--输入系统(十四)Dispatcher线程情景分析_dispatch前处理 1. 回顾 我们知道Android输入系统是Reader线程通过驱动程序得到上报的输入事件,还要经过处理 ...
随机推荐
- SpringBoot之旅 -- 定时任务两种(Spring Schedule 与 Quartz 整合 )实现
相关文章 Spring Boot 相关文章目录 前言 最近在项目中使用到定时任务,之前一直都是使用Quartz 来实现,最近看Spring 基础发现其实Spring 提供 Spring Schedul ...
- 3892: [Usaco2014 Dec]Marathon
3892: [Usaco2014 Dec]Marathon Time Limit: 10 Sec Memory Limit: 128 MBSubmit: 169 Solved: 100[Submi ...
- 3DES 加密 解密
p.p1 { margin: 0.0px 0.0px 0.0px 0.0px; font: 18.0px Menlo; color: #c91b13 } p.p2 { margin: 0.0px 0. ...
- LINQ笔记
LINQ概述 语言集成查询(Language intergrated Query,LINQ)在C#编程语言中集成了查询语法. 可以使用相同的语法访问不同的数据源 提供了不同数据源的抽象层,所有可以使用 ...
- 修改Delphi 10.1.2 edit控件在android的复制、剪切和粘贴样式
Delphi 10.1.2 edit控件在android默认的复制.剪切和粘贴样式太丑,经悟能-DelphiTeacher的提示,用最简单的代码修改后稍有改观. 默认的样式: 修改后的样式: 修改FM ...
- webots自学笔记(五)使用物理插件ODE建立铰链
原创文章,来自"博客园,_阿龙clliu" http://www.cnblogs.com/clliu/,转载请注明原文章出处. 在一些三维制图软件或仿真软件里,都有运动副的概念,w ...
- 用ListView实现对数据库的内容显示
用ListView实现对数据库的内容显示 创建一个触发机制 ---------(作用)将数据读入ArrayList集合中 MyBase base = new MyBase(); SQLiteDatab ...
- TreeSet集合如何保证元素唯一
TreeSet: 1.特点 TreeSet是用来排序的, 可以指定一个顺序, 对象存入之后会按照指定的顺序排列 2.使用方式 a.自然顺序(Comparable) TreeSet类的add()方法中会 ...
- vue学习笔记 计算属性(四)
计算属性就是vue实例里的computed属性,对应一个对象,里面可以放各种方法,方法的作用就是可以生成和数据变量对应的计算后的变量,跟数据相关的复杂逻辑变量,都可以使用计算属性实现,computed ...
- vue学习笔记 概述(一)
vue里 最常见的 最普遍的用法 应该是 var app = new Vue({ el: '#app', data: { message: 'Hello Vue!' }}) 下面把所有使用方法尽可能列 ...