Chinaunix首页 | 论坛 | 博客
  • 博客访问: 2117266
  • 博文数量: 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-06-24 09:53:08

一. EventHub发现设备结点,并对键盘设备加载配置文件
1. 新设备的open过程
当扫描到/dev/input/event*设备结点时,会调用下面这个函数
  1. status_t EventHub::openDeviceLocked(const char *devicePath) {
  2.     int fd = open(devicePath, O_RDWR | O_CLOEXEC);
  3.     ioctl(fd, EVIOCGNAME(sizeof(buffer) - 1), &buffer);
  4.     //用open ioctl与驱动交互将设备的name pid vid写到descriptor中去
  5.     setDescriptor(identifier);
  6.     //顺序产生deviceId    
  7.     int32_t deviceId = mNextDeviceId++;
  8.     //新建一个struct Device
  9.     Device* device = new Device(fd, deviceId, String8(devicePath), identifier);
  10.     loadConfigurationLocked(device); //这个load一般都为null
  11.     //获取各个mask
  12.     ioctl(fd, EVIOCGBIT(EV_KEY, sizeof(device->keyBitmask)), device->keyBitmask);
  13.     ioctl(fd, EVIOCGBIT(EV_ABS, sizeof(device->absBitmask)), device->absBitmask);
  14.     ioctl(fd, EVIOCGBIT(EV_REL, sizeof(device->relBitmask)), device->relBitmask);
  15.     ioctl(fd, EVIOCGBIT(EV_SW, sizeof(device->swBitmask)), device->swBitmask);
  16.     ioctl(fd, EVIOCGBIT(EV_LED, sizeof(device->ledBitmask)), device->ledBitmask);
  17.     ioctl(fd, EVIOCGBIT(EV_FF, sizeof(device->ffBitmask)), device->ffBitmask);
  18.     ioctl(fd, EVIOCGPROP(sizeof(device->propBitmask)), device->propBitmask);
  19.     //对mask进行解析,确定classes
  20.     键盘的classes = 0x61;
  21.     INPUT_DEVICE_CLASS_GAMEPAD|
  22.     INPUT_DEVICE_CLASS_DPAD|
  23.     INPUT_DEVICE_CLASS_KEYBOARD
  24.     
  25.     //键盘与众不同的地方在于,会加载KeyMap
  26.     status_t keyMapStatus = NAME_NOT_FOUND;
  27.     if (device->classes & (INPUT_DEVICE_CLASS_KEYBOARD | INPUT_DEVICE_CLASS_JOYSTICK)) {
  28.         keyMapStatus = loadKeyMapLocked(device);
  29.     }
  30.     //添加到epoll中
  31.     struct epoll_event eventItem;
  32.     memset(&eventItem, 0, sizeof(eventItem));
  33.     eventItem.events = EPOLLIN;
  34.     eventItem.data.u32 = deviceId;
  35.     epoll_ctl(mEpollFd, EPOLL_CTL_ADD, fd, &eventItem);
  36.     //将设备信息保存在全局struct Device数组中.
  37.     addDeviceLocked(device);
  38.     return 0;
  39. }
1.1 键盘设备的loadKeyMap过程
在./framework/base/libs/androidfw/Keyboard.cpp中
EventHub::openDeviceLocked

  --> EventHub::loadKeyMapLocked
    --> KeyMap::load  
status_t KeyMap::load()   //keymap的查找过程
{
    //在/system/usr/keylayout目录中
    //1. 找Vendor_$PID_Product_$VID.kl 或者 $name.kl

    probeKeyMap(deviceIdenfifier, String8::empty());
    //2. 如果找不到就找Generic.kl
    probeKeyMap(deviceIdenfifier, String8("Generic"));
    //3. 还找不找就找Virtual.kl
    probeKeyMap(deviceIdenfifier, String8("Virtual"));
    return NAME_NOT_FOUND;
}
1.1.1 配置文件的加载顺序
EventHub::openDeviceLocked
  --> EventHub::loadKeyMapLocked
    --> KeyMap::load   
        --> 
KeyMap::probeKeyMap
  1. bool KeyMap::probeKeyMap(const InputDeviceIdentifier& deviceIdentifierconst String8& keyMapName) {
  2.     if (!haveKeyLayout()) {   //加载kl文件
  3.         loadKeyLayout(deviceIdentifier, keyMapName);
  4.     }
  5.     if (!haveKeyCharacterMap()) {
  6.         loadKeyCharacterMap(deviceIdentifier, keyMapName);
  7.     }
  8.     return isComplete();
  9. }
找配置文件kl(key layout)的顺序是: 
    a.Vendor_$PID_Product_$VID.kl
   b. $name.kl
   c. Generic.kl
找kcm(Key Character Map)的与kl的顺序一样
    a.Vendor_$PID_Product_$VID.kcm
   b. $name.kcm
   c. Generic.kcm

二.InputReader发现设备并添加mapper
2.1  键盘设盘的添加过程
当设备第一次插入时或者在扫描/dev/input/event*时,inputreader会收到event
  1. void InputReader::loopOnce()
  2. {
  3.     //获取event
  4.     size_t count = mEventHub->getEvents(timeoutMillis, mEventBuffer, EVENT_BUFFER_SIZE);
  5.     if (count) {
  6.         processEventsLocked(mEventBuffer, count); //对event进行处理
  7.     }
  8.     mQueuedListener->flush();
  9. }
InputReader::loopOnce
  --> InputReader::processEventsLocked
  1. void InputReader::processEventsLocked(const RawEvent* rawEvents, size_t count)
  2. {
  3.     for (const RawEvent* rawEvent = rawEvents; count;)
  4.     {
  5.         if (type < EventHubInterface::FIRST_SYNTHETIC_EVENT) {
  6.             //数据处理流程
  7.         } else {
  8.             switch (rawEvent->type) {
  9.                 case EventHubInterface::DEVICE_ADDED: //新发现的设备的处理
  10.                     addDeviceLocked(rawEvent->when, rawEvent->deviceId);
  11.                     break;
  12.                 case EventHubInterface::DEVICE_REMOVED:
  13.                     removeDeviceLocked(rawEvent->when, rawEvent->deviceId);
  14.                     break;
  15.                 case EventHubInterface::FINISHED_DEVICE_SCAN:  //最后会调用这个
  16.                     handleConfigurationChangedLocked(rawEvent->when);
  17.                     break;
  18.                 default:
  19.                     ALOG_ASSERT(false); // can't happen
  20.                     break;
  21.             }
  22.         }
  23.     }
  24. }
2.2 设备添加事件的处理
InputReader::loopOnce
  --> InputReader::processEventsLocked
       --> InputReader::addDeviceLocked
  1. void InputReader::addDeviceLocked(nsecs_t when, int32_t deviceId)
  2. {
  3.     ssize_t deviceIndex = mDevices.indexOfKey(deviceId);
  4.     InputDeviceIdentifier identifier = mEventHub->getDeviceIdentifier(deviceId);
  5.     uint32_t classes = mEventHub->getDeviceClasses(deviceId);

  6.     InputDevice* device = createDeviceLocked(deviceId, identifier, classes);
  7.     device->configure(when, &mConfig, 0);
  8.     device->reset(when);
  9.     mDevices.add(deviceId, device);
  10.     bumpGenerationLocked();
  11. }
2.2.1 addMaper
InputReader::loopOnce

  --> InputReader::processEventsLocked
       --> InputReader::addDeviceLocked
        --> InputReader::createDeviceLocked
键盘设备的classes=0x61,mapper添加的是KeyboardInputMapper
  1. InputDevice* InputReader::createDeviceLocked(int32_t deviceIdconst InputDeviceIdentifier& identifier, uint32_t classes) 
  2. {
  3.     InputDevice* device = new InputDevice(&mContext, deviceId, bumpGenerationLocked(), identifier, classes);
  4.     device->addMapper(new KeyboardInputMapper(device, keyboardSource, keyboardType));
  5.     return device;
  6. }
三. 键盘按键的数据处理流程
3.1  数据事件的处理过程
inputreader会收到event
  1. void InputReader::loopOnce()
  2. {
  3.     //获取event
  4.     size_t count = mEventHub->getEvents(timeoutMillis, mEventBuffer, EVENT_BUFFER_SIZE);
  5.     if (count) {
  6.         processEventsLocked(mEventBuffer, count); //对event进行处理
  7.     }
  8.     mQueuedListener->flush();
  9. }
InputReader::loopOnce
  --> InputReader::processEventsLocked  ;;区分数据与特殊事件
  1. void InputReader::processEventsLocked(const RawEvent* rawEvents, size_t count) {
  2.     for (const RawEvent* rawEvent = rawEvents; count;) {
  3.         int32_t type = rawEvent->type;
  4.         size_t batchSize = 1;
  5.         if (type < EventHubInterface::FIRST_SYNTHETIC_EVENT) {
  6.             processEventsForDeviceLocked(deviceId, rawEvent, batchSize); //处理数据事件
  7.         } else {
  8.                //处理特殊事件,如设备添加删除
  9.         }
  10.         count -= batchSize;
  11.         rawEvent += batchSize;
  12.     }
  13. }
3.2 接收到数据事件后,调用mapper的process
InputReader::loopOnce
  --> InputReader::processEventsLocked  ;;区分数据与特殊事件
       --> InputDevice::process                 ;;增加数据丢失处理后,用for循环对每个事件进行处理
  1. void InputDevice::process(const RawEvent* rawEvents, size_t count) 
  2. {
  3.     size_t numMappers = mMappers.size();
  4.     for (const RawEvent* rawEvent = rawEvents; count--; rawEvent++) {
  5.         if (mDropUntilNextSync) {            //这个标志是进行丢数据异常处理
  6.             if (rawEvent->type == EV_SYN && rawEvent->code == SYN_REPORT) {
  7.                 mDropUntilNextSync = false//直到下一次数据同步才会改变为false
  8.             }
  9.         } else if (rawEvent->type == EV_SYN && rawEvent->code == SYN_DROPPED) {
  10.             mDropUntilNextSync = true;       //所以有数据丢失时是不会进行mapper处理的
  11.             reset(rawEvent->when);
  12.         } else {
  13.             for (size_t i = 0; i < numMappers; i++) {
  14.                 InputMapper* mapper = mMappers[i];
  15.                 mapper->process(rawEvent);
  16.             }
  17.         }
  18.     }
  19. }
3.2.1 mapper的process对单个事件进行处理
InputReader::loopOnce
  --> InputReader::processEventsLocked  ;;区分数据与特殊事件
       --> InputDevice::process                 ;;增加数据丢失处理后,用for循环对每个事件进行处理
        -->  KeyboardInputMapper::process ;;单件event的数据处理
  1. void KeyboardInputMapper::process(const RawEvent* rawEvent) {
  2.     switch (rawEvent->type) {
  3.     case EV_KEY: {             //只对type=0x01(EV_KEY)的事件进行处理
  4.         //3.2.2 解析映射过程
  5.         if (isKeyboardOrGamepadKey(scanCode)) {
  6.             int32_t keyCode;
  7.             uint32_t flags;
  8.             if (getEventHub()->mapKey(getDeviceId(), scanCode, usageCode, &keyCode, &flags)) {
  9.                 keyCode = AKEYCODE_UNKNOWN;
  10.                 flags = 0;
  11.             }
  12.             processKey(rawEvent->when, rawEvent->value != 0, keyCode, scanCode, flags);
  13.         }
  14.         break;
  15.     }
  16.     case EV_MSC:              //其它的事件只是设个标志位,不关心
  17.         break;
  18.     case EV_SYN: 
  19.         break;
  20.     }
  21. }
3.2.2 解析映射过程
例如:/system/usr/keylayout/Generic.kl有如下片断
  1. key 256 BUTTON_1
  2. key 257 BUTTON_2
  3. key 258 BUTTON_3
  4. key 259 BUTTON_4
  5. key 260 BUTTON_5
  6. key 261 BUTTON_6
当接收到的scanCode=256时,在这个kl中会映射成BUTTON_1,而BUTTON_1又是什么呢?
在./frameworks/native/include/android/keycodes.h中,是标准的android键值.
  1. AKEYCODE_BUTTON_1 = 188,
  2. AKEYCODE_BUTTON_2 = 189,
  3. AKEYCODE_BUTTON_3 = 190,
  4. AKEYCODE_BUTTON_4 = 191,
  5. AKEYCODE_BUTTON_5 = 192,
  6. AKEYCODE_BUTTON_6 = 193,
AKEYCODE_BUTTON_1=188,所以scanCode=256就映射成了keyCode=188.
3.2.3
InputReader::loopOnce
  --> InputReader::processEventsLocked  ;;区分数据与特殊事件
       --> InputDevice::process                 ;;增加数据丢失处理后,用for循环对每个事件进行处理
        -->  KeyboardInputMapper::process ;;单件event的数据处理,按type区分事件类型
            -->  KeyboardInputMapper::processKey ;;只对type=0x01(EV_KEY)处理
调用processKey(rawEvent->when, rawEvent->value != 0, keyCode, scanCode, flags);
  1. void KeyboardInputMapper::processKey(nsecs_t when, bool down, int32_t keyCode,
  2.         int32_t scanCode, uint32_t policyFlags)
  3. {
  4.     if (down) { //按下状态
  5.         if (mParameters.orientationAware && mParameters.hasAssociatedDisplay)
  6.             keyCode = rotateKeyCode(keyCode, mOrientation); //看来旋转是在这儿处理的,不过此时不关心

  7.         ssize_t keyDownIndex = findKeyDown(scanCode);
  8.         if (keyDownIndex >= 0) {
  9.             keyCode = mKeyDowns.itemAt(keyDownIndex).keyCode;
  10.         } else {
  11.             mKeyDowns.push();
  12.             KeyDown& keyDown = mKeyDowns.editTop();
  13.             keyDown.keyCode = keyCode;
  14.             keyDown.scanCode = scanCode;
  15.         }
  16.         mDownTime = when;
  17.     } else {
  18.         ssize_t keyDownIndex = findKeyDown(scanCode);
  19.         if (keyDownIndex >= 0) {
  20.             keyCode = mKeyDowns.itemAt(keyDownIndex).keyCode;
  21.             mKeyDowns.removeAt(size_t(keyDownIndex));
  22.         }
  23.     }
  24.     bool metaStateChanged = false;
  25.     int32_t oldMetaState = mMetaState;
  26.     int32_t newMetaState = updateMetaState(keyCode, down, oldMetaState);
  27.     if (oldMetaState != newMetaState) {
  28.         mMetaState = newMetaState;
  29.         metaStateChanged = true;
  30.         updateLedState(false);
  31.     }
  32.     //上面的没有仔细看
  33.     //这个args,会区分down与up事件
  34.     //这个地方组成一个args,调用notifyKey.
  35.     NotifyKeyArgs args(when, getDeviceId(), mSource, policyFlags,
  36.             down ? AKEY_EVENT_ACTION_DOWN : AKEY_EVENT_ACTION_UP,
  37.             AKEY_EVENT_FLAG_FROM_SYSTEM, keyCode, scanCode, newMetaState, downTime);
  38.     getListener()->notifyKey(&args);
  39. }
getListener()->notifyKey(&args);即调用的是InputDispatcher::notifyKey
四. inputDispatcher的处理
InputReader::loopOnce
  --> InputReader::processEventsLocked  ;;区分数据与特殊事件
       --> InputDevice::process                 ;;增加数据丢失处理后,用for循环对每个事件进行处理
        -->  KeyboardInputMapper::process ;;单件event的数据处理,按type区分事件类型
            -->  KeyboardInputMapper::processKey ;;只对type=0x01(EV_KEY)处理
                --> InputDispatcher::notifyKey
将args重新组装成一个keyEntry并插入到队列中,最后唤醒队列,并进行处理
  1. void InputDispatcher::notifyKey(const NotifyKeyArgs* args) 
  2. {
  3.     //在因构造函数中会加入EventEntry(TYPE_KEY, eventTime, policyFlags)
  4.     //类型为TYPE_KEY
  5.    KeyEntry* newEntry = new KeyEntry(args->eventTime,
  6.        args->deviceId, args->source, policyFlags,
  7.        args->action, flags, args->keyCode, args->scanCode,
  8.        metaState, repeatCount, args->downTime);

  9.     needWake = enqueueInboundEventLocked(newEntry);
  10.     if (needWake) {
  11.         mLooper->wake();
  12.     }
  13. }
mLooper->wake这个wake是唤醒了什么东东呢?
原来在InputDispatcher中有一个mLooper会一直poll,当上面的wake执行时会让pollOnce返回,
并执行dispatchOnceInnerLocked.
4.1 InputDispatcher中的poll
  1. void InputDispatcher::dispatchOnce() 
  2. {
  3.     nsecs_t nextWakeupTime = LONG_LONG_MAX;
  4.     {
  5.         AutoMutex _l(mLock);
  6.         mDispatcherIsAliveCondition.broadcast();
  7.         if (!haveCommandsLocked()) {
  8.             dispatchOnceInnerLocked(&nextWakeupTime);   //当有事件唤醒时就会执行这个函数
  9.         }
  10.         if (runCommandsLockedInterruptible()) {
  11.             nextWakeupTime = LONG_LONG_MIN;
  12.         }
  13.     }    
  14.     nsecs_t currentTime = now();
  15.     int timeoutMillis = toMillisecondTimeoutDelay(currentTime, nextWakeupTime);
  16.     mLooper->pollOnce(timeoutMillis);   //在这儿等侍事件的发生
  17. }
4.2 wake之后执行的函数
  1. void InputDispatcher::dispatchOnceInnerLocked(nsecs_t* nextWakeupTime)
  2. {
  3. case EventEntry::TYPE_KEY:
  4.         done = dispatchKeyLocked(currentTime, typedEntry, &dropReason, nextWakeupTime);
  5.         break;
  6. }


在./frameworks/native/libs/utils/Looper.cpp中
  1. void Looper::wake() {
  2.     ssize_t nWrite;
  3.     do {
  4.         nWrite = write(mWakeWritePipeFd, "W", 1);   //向管道中写入一个值,然后管道中有数据变化就会唤醒.
  5.     } while (nWrite == -1 && errno == EINTR);
  6. }




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