Chinaunix首页 | 论坛 | 博客
  • 博客访问: 2112629
  • 博文数量: 438
  • 博客积分: 3871
  • 博客等级: 中校
  • 技术积分: 6075
  • 用 户 组: 普通用户
  • 注册时间: 2011-09-10 00:11
个人简介

邮箱: wangcong02345@163.com

文章分类

全部博文(438)

文章存档

2017年(15)

2016年(119)

2015年(91)

2014年(62)

2013年(56)

2012年(79)

2011年(16)

分类: Android平台

2014-02-10 09:28:47

inputManager
     |
inputReader    --> inputDispatcher
     |
eventHub
     |
driver
一. 设备的添加过程
对于/dev/input下的设备结点,开机时会自动扫描一下,
同时也添加了监测,每当设备结点有变化(usb鼠标插入)时都会再扫描一下.
下面只分析开机扫描/dev/input/的过程,监测过程类似.
在./frameworks/base/services/input/EventHub.cpp中
  1. size_t EventHub::getEvents(int timeoutMillis, RawEvent* buffer, size_t bufferSize) {
  2.     if (mNeedToScanDevices) {       //初始化为true,所以需要扫描/dev/input目录
  3.          mNeedToScanDevices = false;
  4.          scanDevicesLocked();
  5.          mNeedToSendFinishedDeviceScan = true;
  6.          }
  7. }

getEvents
  --> scanDevicesLocked
  1. void EventHub::scanDevicesLocked() {
  2.     status_t res = scanDirLocked(DEVICE_PATH);   //这个DEVICE_PATH就是/dev/input目录
  3.     if (mDevices.indexOfKey(VIRTUAL_KEYBOARD_ID) < 0) {
  4.         createVirtualKeyboardLocked();
  5.     }
  6. }

getEvents
  --> scanDevicesLocked
     --> scanDirLocked
  1. status_t EventHub::scanDirLocked(const char *dirname)
  2. {
  3.     dir = opendir(dirname);
  4.      while((de = readdir(dir))) {
  5.         //在/dev/input目录下,对于找到的每一个设备都调用openDeviceLocked
  6.            openDeviceLocked(devname);  
  7.     }
  8.     closedir(dir);
  9.     return 0;
  10. }

getEvents
  --> scanDevicesLocked
     --> scanDirLocked
        --> opendeviceLocked
  1. status_t EventHub::openDeviceLocked(const char *devicePath)
  2. {
  3.     //open设备文件,并用ioctl 获取设备信息,
  4.     ...
  5.     //最重要的是deviceId,它是顺次累加的
  6.     int32_t deviceId = mNextDeviceId++;
  7.     //初始化 设备扫述符identifier
  8.     identifier.value = something 
  9.     //new Device,其deviceID就是刚才累加的值
  10.     Device* device = new Device(fd, deviceId, String8(devicePath), identifier);
  11.     
  12.     //利用ioctl获取设备的上报类型
  13.     ioctl(fd, EVIOCGBIT(EV_KEY, sizeof(device->keyBitmask)), device->keyBitmask);
  14.     //并将设备的上报类型放在classes中(下方是tpd)
  15.     device->classes |= INPUT_DEVICE_CLASS_TOUCH | INPUT_DEVICE_CLASS_TOUCH_MT;
  16.     
  17.     //最后调用addDeviceLocked,把新创建的device放在mDevice链表中
  18.     addDeviceLocked(device);
  19. }

getEvents
  --> scanDevicesLocked
     --> scanDirLocked
        --> opendeviceLocked
            --> addDeviceLocked
  1. void EventHub::addDeviceLocked(Device* device) {
  2.     mDevices.add(device->id, device); //添加到mDevice链表中
  3.     device->next = mOpeningDevices;
  4.     mOpeningDevices = device;
  5. }


二. 设备事件的处理
都是在./frameworks/base/services/input/InputReader.cpp中
  1. bool InputReaderThread::threadLoop() {
  2.     mReader->loopOnce();
  3.     return true;
  4. }
threadLoop
  --> loopOnce
  1. void InputReader::loopOnce() {
  2.     mEventHub->getEvents();   //从eventHub中获取事件
  3.     processEventsLocked(mEventBuffer, count); //调用这个函数来处理
  4. }

threadLoop
  --> loopOnce
    --> processEventsLocked
  1. processEventsLocked(mEventBuffer, count)
  2. {
  3.     //区分特殊事件与数据事件,然后调用各自的函数进行处理

  4.     //android是如何区分特殊事件与数据事件呢?
  5.     //特殊事件的值都很大:DEVICE_ADDED=0x10000000, DEVICE_REMOVED=0x20000000
  6.     //而数据事件的值都小(0-->report, 1->key, 3->joystick&&touch)
  7.     
  8.     if (type < EventHubInterface::FIRST_SYNTHETIC_EVENT)
  9.            processEventsForDeviceLocked(deviceId, rawEvent, batchSize);
  10.     else{
  11.      addDeviceLocked(rawEvent->when, rawEvent->deviceId);  //
  12.      removeDeviceLocked(rawEvent->when, rawEvent->deviceId);
  13.      handleConfigurationChangedLocked(rawEvent->when);
  14.     }
  15. }
2.1 特殊事件的处理
特殊事件包括: addDevice, removeDevice, handleConfigurationChanged
threadLoop
  --> loopOnce
    --> processEventsLocked
        --> addDeviceLocked    ;;特殊事件的处理
注意:EventHub中添加的类型为Device, 这儿把Device转为了InputDevice
即要筛选出非InputDevice,只将InputDevice添加到device列表中
  1. void InputReader::addDeviceLocked(nsecs_t when, int32_t deviceId) {
  2.     ssize_t deviceIndex = mDevices.indexOfKey(deviceId);

  3.     InputDeviceIdentifier identifier = mEventHub->getDeviceIdentifier(deviceId);
  4.     uint32_t classes = mEventHub->getDeviceClasses(deviceId);

  5.     InputDevice* device = createDeviceLocked(deviceId, identifier, classes);
  6.     device->configure(when, &mConfig, 0);
  7.     device->reset(when);

  8.     mDevices.add(deviceId, device);
  9.     bumpGenerationLocked();
  10. }
threadLoop
  --> loopOnce
    --> processEventsLocked
        --> addDeviceLocked         ;;特殊事件的处理
           --> createDeviceLocked   ;;对于add事件的处理
  1. InputDevice* InputReader::createDeviceLocked(int32_t deviceId,) {
  2.     InputDevice* device = new InputDevice();
  3.     //添加设备的mapper,即具体设备的处理函数
  4.     //例如tp的设备,需要用到MultiTouchInputMapper
  5.     if (classes & INPUT_DEVICE_CLASS_TOUCH_MT) {
  6.         device->addMapper(new MultiTouchInputMapper(device));
  7.     } else if (classes & INPUT_DEVICE_CLASS_TOUCH) {
  8.         device->addMapper(new SingleTouchInputMapper(device));
  9.     }
  10.     return device;
  11. }
2.2 数据事件的处理(以触摸屏为例)
threadLoop
  --> loopOnce
    --> processEventsLocked
        --> processEventsForDeviceLocked    ;;数据事件的处理
  1. void InputReader::processEventsForDeviceLocked(int32_t deviceId, ...) {
  2.     ssize_t deviceIndex = mDevices.indexOfKey(deviceId);  //由deviceId获取device
  3.     InputDevice* device = mDevices.valueAt(deviceIndex);
  4.     device->process(rawEvents, count);                     //然后调用device的处理函数
  5. }
threadLoop
  --> loopOnce
    --> processEventsLocked
        --> InputReader::processEventsForDeviceLocked    ;;数据事件的处理
        --> InputDevice::process
  1. void InputDevice::process(const RawEvent* rawEvents, size_t count) {
  2.     size_t numMappers = mMappers.size();
  3.     for (const RawEvent* rawEvent = rawEvents; count--; rawEvent++) {
  4.         if (mDropUntilNextSync) {
  5.             if (rawEvent->type == EV_SYN && rawEvent->code == SYN_REPORT) {
  6.                 mDropUntilNextSync = false;
  7.             }
  8.         } else if (rawEvent->type == EV_SYN && rawEvent->code == SYN_DROPPED) {
  9.             mDropUntilNextSync = true;
  10.             reset(rawEvent->when);
  11.         } else {
  12.             for (size_t i = 0; i < numMappers; i++) {
  13.                 InputMapper* mapper = mMappers[i];
  14.                 mapper->process(rawEvent);                  //调用mapper进行处理
  15.             }
  16.         }
  17.     }
  18. }
threadLoop
  --> loopOnce
    --> processEventsLocked
        --> InputReader::processEventsForDeviceLocked    ;;数据事件的处理
        --> InputDevice::process (mapper的process)
            --> TouchInputMapper::process    ;;具体事件的处理(touch)
  1. void TouchInputMapper::process(const RawEvent* rawEvent) {
  2.     if (rawEvent->type == EV_SYN && rawEvent->code == SYN_REPORT) {
  3.         sync(rawEvent->when);
  4.     }
  5. }

  6. void TouchInputMapper::sync(nsecs_t when) {
  7.     cookPointerData();
  8.     dispatchHoverExit(when, policyFlags);
  9.     dispatchTouches(when, policyFlags);
  10.     dispatchHoverEnterAndMove(when, policyFlags);
  11. }


  12. void TouchInputMapper::dispatchTouches(nsecs_t when, uint32_t policyFlags) {
  13.          dispatchMotion(...);
  14.  }

  15. void TouchInputMapper::dispatchMotion(...)

  16.     NotifyMotionArgs args(when, getDeviceId(), source, policyFlags,
  17.             action, flags, metaState, buttonState, edgeFlags,
  18.             mViewport.displayId, pointerCount, pointerProperties, pointerCoords,
  19.             xPrecision, yPrecision, downTime);
  20.     getListener()->notifyMotion(&args);   //只是将args压出栈中,在flush中统一处理
  21. }
三. touch的process
3.1 touch的mapper添加过程
  1. InputDevice* InputReader::createDeviceLocked(int32_t deviceId,) {
  2.     InputDevice* device = new InputDevice();
  3.     //添加设备的mapper,即具体设备的处理函数
  4.     //例如tp的设备,需要用到MultiTouchInputMapper
  5.     if (classes & INPUT_DEVICE_CLASS_TOUCH_MT) {
  6.         device->addMapper(new MultiTouchInputMapper(device));
  7.     } else if (classes & INPUT_DEVICE_CLASS_TOUCH) {
  8.         device->addMapper(new SingleTouchInputMapper(device));
  9.     }
  10.     return device;
  11. }
其实质就是调用其成员变最mMppers.add过程
  1. void InputDevice::addMapper(InputMapper* mapper) {
  2.     mMappers.add(mapper);
  3. }
再来看一下这个MultiTouchInputMapper,它继承自TouchInputMapper
  1. MultiTouchInputMapper::MultiTouchInputMapper(InputDevice* device) :
  2.         TouchInputMapper(device) {
  3. }
3.2 调用mapper进行处理
现在来了一个touch事件,要进行处理了
  1. void InputDevice::process(const RawEvent* rawEvents, size_t count) {
  2.     for (size_t i = 0; i < numMappers; i++) {
  3.         InputMapper* mapper = mMappers[i];
  4.         mapper->process(rawEvent); //对每一条event都调用MulitTouchInputMapper进行处理
  5.     }
  6. }
MulitTouchInputMapper的process又分为两个过程:TouchInputMapper与MultiTouchMotionAccumulator
  1. void MultiTouchInputMapper::process(const RawEvent* rawEvent) {
  2.     TouchInputMapper::process(rawEvent); //3.2.1 TouchInputMapper的process
  3.     mMultiTouchMotionAccumulator.process(rawEvent); //3.2.2 MultiTouchMotionAccumulator::process
  4. }
3.2.1 TouchInputMapper::process
  1. void TouchInputMapper::process(const RawEvent* rawEvent) {
  2.     mCursorButtonAccumulator.process(rawEvent);  //只对EV_KEY(0x01)处理,即只对( 0001 014a 00000001)用,但实际上没有case,
  3.     mCursorScrollAccumulator.process(rawEvent);  //只对EV_REL(0x02)处理,但touch只有(3 或 1),所以这儿
  4.     mTouchButtonAccumulator.process(rawEvent);   //只对EV_KEY(0x01)处理,但touch是即只对( 0001 014a 00000001)
  5.         //mBtnTouch = rawEvent->value;记录了type=01value

  6.     if (rawEvent->type == EV_SYN && rawEvent->code == SYN_REPORT) {
  7.         sync(rawEvent->when);    //上面三个process只是记录了type=1时的value值,重点是这个函数
  8.     }
  9. }

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

阅读(2772) | 评论(0) | 转发(1) |
给主人留下些什么吧!~~