rk3188--5.android input 系统架构分析

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

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值