inputManager
|
inputReader --> inputDispatcher
|
eventHub
|
driver
一. 设备的添加过程
对于/dev/input下的设备结点,开机时会自动扫描一下,
同时也添加了监测,每当设备结点有变化(usb鼠标插入)时都会再扫描一下.
下面只分析开机扫描/dev/input/的过程,监测过程类似.
在./frameworks/base/services/input/EventHub.cpp中
-
size_t EventHub::getEvents(int timeoutMillis, RawEvent* buffer, size_t bufferSize) {
-
if (mNeedToScanDevices) { //初始化为true,所以需要扫描/dev/input目录
-
mNeedToScanDevices = false;
-
scanDevicesLocked();
-
mNeedToSendFinishedDeviceScan = true;
-
}
-
}
getEvents
--> scanDevicesLocked
-
void EventHub::scanDevicesLocked() {
-
status_t res = scanDirLocked(DEVICE_PATH); //这个DEVICE_PATH就是/dev/input目录
-
if (mDevices.indexOfKey(VIRTUAL_KEYBOARD_ID) < 0) {
-
createVirtualKeyboardLocked();
-
}
-
}
getEvents
--> scanDevicesLocked
--> scanDirLocked
-
status_t EventHub::scanDirLocked(const char *dirname)
-
{
-
dir = opendir(dirname);
-
while((de = readdir(dir))) {
-
//在/dev/input目录下,对于找到的每一个设备都调用openDeviceLocked
-
openDeviceLocked(devname);
-
}
-
closedir(dir);
-
return 0;
-
}
getEvents
--> scanDevicesLocked
--> scanDirLocked
--> opendeviceLocked
-
status_t EventHub::openDeviceLocked(const char *devicePath)
-
{
-
//open设备文件,并用ioctl 获取设备信息,
-
...
-
//最重要的是deviceId,它是顺次累加的
-
int32_t deviceId = mNextDeviceId++;
-
//初始化 设备扫述符identifier
-
identifier.value = something
-
//new Device,其deviceID就是刚才累加的值
-
Device* device = new Device(fd, deviceId, String8(devicePath), identifier);
-
-
//利用ioctl获取设备的上报类型
-
ioctl(fd, EVIOCGBIT(EV_KEY, sizeof(device->keyBitmask)), device->keyBitmask);
-
//并将设备的上报类型放在classes中(下方是tpd)
-
device->classes |= INPUT_DEVICE_CLASS_TOUCH | INPUT_DEVICE_CLASS_TOUCH_MT;
-
-
//最后调用addDeviceLocked,把新创建的device放在mDevice链表中
-
addDeviceLocked(device);
-
}
getEvents
--> scanDevicesLocked
--> scanDirLocked
--> opendeviceLocked
--> addDeviceLocked
-
void EventHub::addDeviceLocked(Device* device) {
-
mDevices.add(device->id, device); //添加到mDevice链表中
-
device->next = mOpeningDevices;
-
mOpeningDevices = device;
-
}
二. 设备事件的处理
都是在./frameworks/base/services/input/InputReader.cpp中
-
bool InputReaderThread::threadLoop() {
-
mReader->loopOnce();
-
return true;
-
}
threadLoop
--> loopOnce
-
void InputReader::loopOnce() {
-
mEventHub->getEvents(); //从eventHub中获取事件
-
processEventsLocked(mEventBuffer, count); //调用这个函数来处理
-
}
threadLoop
--> loopOnce
--> processEventsLocked
-
processEventsLocked(mEventBuffer, count)
-
{
-
//区分特殊事件与数据事件,然后调用各自的函数进行处理
-
-
//android是如何区分特殊事件与数据事件呢?
-
//特殊事件的值都很大:DEVICE_ADDED=0x10000000, DEVICE_REMOVED=0x20000000
-
//而数据事件的值都小(0-->report, 1->key, 3->joystick&&touch)等
-
-
if (type < EventHubInterface::FIRST_SYNTHETIC_EVENT)
-
processEventsForDeviceLocked(deviceId, rawEvent, batchSize);
-
else{
-
addDeviceLocked(rawEvent->when, rawEvent->deviceId); //
-
removeDeviceLocked(rawEvent->when, rawEvent->deviceId);
-
handleConfigurationChangedLocked(rawEvent->when);
-
}
-
}
2.1 特殊事件的处理
特殊事件包括: addDevice, removeDevice, handleConfigurationChanged
threadLoop
--> loopOnce
--> processEventsLocked
--> addDeviceLocked ;;特殊事件的处理
注意:EventHub中添加的类型为Device
, 这儿把Device
转为了InputDevice
即要筛选出非InputDevice,只将InputDevice添加到device列表中
-
void InputReader::addDeviceLocked(nsecs_t when, int32_t deviceId) {
-
ssize_t deviceIndex = mDevices.indexOfKey(deviceId);
-
-
InputDeviceIdentifier identifier = mEventHub->getDeviceIdentifier(deviceId);
-
uint32_t classes = mEventHub->getDeviceClasses(deviceId);
-
-
InputDevice* device = createDeviceLocked(deviceId, identifier, classes);
-
device->configure(when, &mConfig, 0);
-
device->reset(when);
-
-
mDevices.add(deviceId, device);
-
bumpGenerationLocked();
-
}
threadLoop
--> loopOnce
--> processEventsLocked
--> addDeviceLocked ;;特殊事件的处理
--> createDeviceLocked ;;对于add事件的处理
-
InputDevice* InputReader::createDeviceLocked(int32_t deviceId,) {
-
InputDevice* device = new InputDevice();
-
//添加设备的mapper,即具体设备的处理函数
-
//例如tp的设备,需要用到MultiTouchInputMapper
-
if (classes & INPUT_DEVICE_CLASS_TOUCH_MT) {
-
device->addMapper(new MultiTouchInputMapper(device));
-
} else if (classes & INPUT_DEVICE_CLASS_TOUCH) {
-
device->addMapper(new SingleTouchInputMapper(device));
-
}
-
return device;
-
}
2.2 数据事件的处理(以触摸屏为例)
threadLoop
--> loopOnce
--> processEventsLocked
-->
processEventsForDeviceLocked ;;数据事件的处理
-
void InputReader::processEventsForDeviceLocked(int32_t deviceId, ...) {
-
ssize_t deviceIndex = mDevices.indexOfKey(deviceId); //由deviceId获取device
-
InputDevice* device = mDevices.valueAt(deviceIndex);
-
device->process(rawEvents, count); //然后调用device的处理函数
-
}
threadLoop
--> loopOnce
--> processEventsLocked
-->
InputReader::processEventsForDeviceLocked ;;数据事件的处理
--> InputDevice::process
-
void InputDevice::process(const RawEvent* rawEvents, size_t count) {
-
size_t numMappers = mMappers.size();
-
for (const RawEvent* rawEvent = rawEvents; count--; rawEvent++) {
-
if (mDropUntilNextSync) {
-
if (rawEvent->type == EV_SYN && rawEvent->code == SYN_REPORT) {
-
mDropUntilNextSync = false;
-
}
-
} else if (rawEvent->type == EV_SYN && rawEvent->code == SYN_DROPPED) {
-
mDropUntilNextSync = true;
-
reset(rawEvent->when);
-
} else {
-
for (size_t i = 0; i < numMappers; i++) {
-
InputMapper* mapper = mMappers[i];
-
mapper->process(rawEvent); //调用mapper进行处理
-
}
-
}
-
}
-
}
threadLoop
--> loopOnce
--> processEventsLocked
-->
InputReader::processEventsForDeviceLocked ;;数据事件的处理
--> InputDevice::process (mapper的process)
-->
TouchInputMapper::process ;;具体事件的处理(touch)
-
void TouchInputMapper::process(const RawEvent* rawEvent) {
-
if (rawEvent->type == EV_SYN && rawEvent->code == SYN_REPORT) {
-
sync(rawEvent->when);
-
}
-
}
-
-
void TouchInputMapper::sync(nsecs_t when) {
-
cookPointerData();
-
dispatchHoverExit(when, policyFlags);
-
dispatchTouches(when, policyFlags);
-
dispatchHoverEnterAndMove(when, policyFlags);
-
}
-
-
-
void TouchInputMapper::dispatchTouches(nsecs_t when, uint32_t policyFlags) {
-
dispatchMotion(...);
-
}
-
-
void TouchInputMapper::dispatchMotion(...)
-
-
NotifyMotionArgs args(when, getDeviceId(), source, policyFlags,
-
action, flags, metaState, buttonState, edgeFlags,
-
mViewport.displayId, pointerCount, pointerProperties, pointerCoords,
-
xPrecision, yPrecision, downTime);
-
getListener()->notifyMotion(&args); //只是将args压出栈中,在flush中统一处理
-
}
三. touch的process
3.1 touch的mapper添加过程
-
InputDevice* InputReader::createDeviceLocked(int32_t deviceId,) {
-
InputDevice* device = new InputDevice();
-
//添加设备的mapper,即具体设备的处理函数
-
//例如tp的设备,需要用到MultiTouchInputMapper
-
if (classes & INPUT_DEVICE_CLASS_TOUCH_MT) {
-
device->addMapper(new MultiTouchInputMapper(device));
-
} else if (classes & INPUT_DEVICE_CLASS_TOUCH) {
-
device->addMapper(new SingleTouchInputMapper(device));
-
}
-
return device;
-
}
其实质就是调用其成员变最mMppers.add过程
-
void InputDevice::addMapper(InputMapper* mapper) {
-
mMappers.add(mapper);
-
}
再来看一下这个MultiTouchInputMapper,它继承自TouchInputMapper
-
MultiTouchInputMapper::MultiTouchInputMapper(InputDevice* device) :
-
TouchInputMapper(device) {
-
}
3.2 调用mapper进行处理
现在来了一个touch事件,要进行处理了
-
void InputDevice::process(const RawEvent* rawEvents, size_t count) {
-
for (size_t i = 0; i < numMappers; i++) {
-
InputMapper* mapper = mMappers[i];
-
mapper->process(rawEvent); //对每一条event都调用MulitTouchInputMapper进行处理
-
}
-
}
MulitTouchInputMapper的process又分为两个过程:TouchInputMapper与
MultiTouchMotionAccumulator
-
void MultiTouchInputMapper::process(const RawEvent* rawEvent) {
-
TouchInputMapper::process(rawEvent); //3.2.1 TouchInputMapper的process
-
mMultiTouchMotionAccumulator.process(rawEvent); //3.2.2 MultiTouchMotionAccumulator::process
-
}
3.2.1
TouchInputMapper::process
-
void TouchInputMapper::process(const RawEvent* rawEvent) {
-
mCursorButtonAccumulator.process(rawEvent); //只对EV_KEY(0x01)处理,即只对( 0001 014a 00000001)起作用,但实际上没有case,
-
mCursorScrollAccumulator.process(rawEvent); //只对EV_REL(0x02)处理,但touch只有(3 或 1),所以这儿不起作用
-
mTouchButtonAccumulator.process(rawEvent); //只对EV_KEY(0x01)处理,但touch是即只对( 0001 014a 00000001)起作用
-
//mBtnTouch = rawEvent->value;记录了type=01时的value值
-
-
if (rawEvent->type == EV_SYN && rawEvent->code == SYN_REPORT) {
-
sync(rawEvent->when); //上面三个process只是记录了type=1时的value值,重点是这个函数
-
}
-
}
3.2.2
参考文章:
Android 4.2 输入研究心得
http://www.eoeandroid.com/home.php?mod=space&uid=10407&do=blog&id=5070
Android 4.1 input 系统从frameworks到kernel
http://blog.chinaunix.net/uid-27167114-id-3347185.html
阅读(2830) | 评论(0) | 转发(1) |