如果大家只想使用输入子系统,而不是深入了解,那么这个小节是可以跳过的,这节主要是对输入子系统,解析配置文件的源码进行追踪和讲解。下面我们开始阅读android源代码,看看在输入子系统里面是使用那些类或者结构体来表示这些文件的。
打开源码文件EventHub.cpp,搜索open,找到EventHub::openDeviceLocked()函数:
EventHub::openDeviceLocked()
fd = open(devicePath, O_RDWR | O_CLOEXEC);//打开设备
ioctl(fd, EVIOCGID, &inputId)) { //通过ioctl获取设备信息
identifier.bus = inputId.bustype; //获得总线类型
identifier.product = inputId.product;//获得PID
identifier.vendor = inputId.vendor;//获得VID
identifier.version = inputId.version;//获得版本好
device = new Device(fd, deviceId, String8(devicePath), identifier);//创建一个device结构体
loadConfigurationLocked(device);//读取配置idc文件
keyMapStatus = loadKeyMapLocked(device);
keyMap.load(device->identifier, device->configuration);
loadKeyLayout(deviceIdenfifier, keyLayoutName);//加载kl文件
loadKeyCharacterMap(deviceIdenfifier, keyCharacterMapName);//加载kcm文件
其中上述的idc文件一般存放于以下路径: 系统其中时,会按照上述的路径逐个进行查找,他的格式十分的简单,一个属性对应一个值(property = value),如:
device.internal = 1 //表示这个输入设备是内嵌在安卓产品中。
在上小节贴出的框图: 成员configurationFile就是idc文件的路径,configuration就是idc的属性,其中的keyMap包括了,从keylayout与kcm文件中解析出来的某些结构体,如下:
根据上图我们可以看到KeyLayoutMap与KeyCharacterMap,分别如下:
上部分int32_t是一个扫描码,如存在对个配置文件,对每个配置文件进行编号,其中key是代表设备(device)上报的相关信息,左边部分的keyCode就是安卓使用的AKEYCODE_xxx,当内核上报一个扫描码之后,根据int32_t(扫描码)取出一个Key,从这个Key中,我们可以知道与驱动上报对应的AKEYCODE是什么。
查看Generic.kl文件看到诸多如下内容:
key 1 ESCAPE
key 2 1
key 3 2
key 4 3
......
key 11 0
key 12 MINUS
key 13 EQUALS
下半部分,假设输入事件为key 2 1,那么在 中,inint_t为2,key为(AKEYCODE_1,0),其中flag可以存在3个选值:
其中的VIRTIAL:有时候我们的按键是在电容屏上,用某些区域进行模拟的,对于这些特殊的按键需要加上VIRTIAL,android在对待这些按键的时候,会做一些容错的处理,避免一些误操作,下面我们开始讲解KeyCharacterMap。
我们介意注意到,类的成员与KeyLayoutMap十分的类似,他是可以实现kl文件的功能,只是写法不一样,需要在前面加上一个map:
但是在该文件,不会进行该些操作, 首先需要从配置文件中取得一个类似如下的的信息:
key B {
label: 'B' //打印在按键上的文字,仅仅是提示作用
base: 'b' //如果没有其他的按键(shift,ctrl等)同时按下,这对应'b'
shift, capslock: 'B'//如果按下capslock再加B键,这对应为'B'
}
使用 进行描述,其中Key保存相关信息,具体成员分部如下:
在上图的Key中存在三个成员,label,number,firstBehavior。三个之中除了label,其余都会生成一个Behavior的类,用来区分是否按下了其他的按键,如shift等等。
看图中,我们可以知道 shift, capslock共会构造两个Behavior, base: 构造一个Behavior,最后firstBehavior会把所有的Behavior连接起来。
讲解到这里Reader线程涉及的类,基本已经讲解完毕,在EventHub.cpp中,EventHub表示对个输入设备,那么肯定需要一个成员来表示这些类,这个成员就是 KeyedVector mDevices,存在一个编号和Device,Device中存在fd,表示打开的设备获得的文件句柄,打开之后通过ioctrl获取其设备相关信息,然后根据这些信息去读取idc,kl或者kcm文件。