一. EventHub发现设备结点,并对键盘设备加载配置文件
1. 新设备的open过程
当扫描到/dev/input/event*设备结点时,会调用下面这个函数
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
找配置文件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
InputReader::loopOnce
--> InputReader::processEventsLocked
2.2 设备添加事件的处理
InputReader::loopOnce
--> InputReader::processEventsLocked
--> InputReader::addDeviceLocked
2.2.1 addMaper
InputReader::loopOnce
--> InputReader::processEventsLocked
--> InputReader::addDeviceLocked
--> InputReader::createDeviceLocked
键盘设备的classes=0x61,mapper添加的是KeyboardInputMapper
三. 键盘按键的数据处理流程
3.1 数据事件的处理过程
inputreader会收到event
InputReader::loopOnce
--> InputReader::processEventsLocked ;;区分数据与特殊事件
3.2 接收到数据事件后,调用mapper的process
InputReader::loopOnce
--> InputReader::processEventsLocked ;;区分数据与特殊事件
--> InputDevice::process ;;增加数据丢失处理后,用for循环对每个事件进行处理
3.2.1 mapper的process对单个事件进行处理
InputReader::loopOnce
--> InputReader::processEventsLocked ;;区分数据与特殊事件
--> InputDevice::process ;;增加数据丢失处理后,用for循环对每个事件进行处理
--> KeyboardInputMapper::process ;;单件event的数据处理
3.2.2 解析映射过程
例如:/system/usr/keylayout/Generic.kl有如下片断
当接收到的scanCode=256时,在这个kl中会映射成BUTTON_1,而BUTTON_1又是什么呢?
在./frameworks/native/include/android/keycodes.h中,是标准的android键值.
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);
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并插入到队列中,最后唤醒队列,并进行处理
mLooper->wake这个wake是唤醒了什么东东呢?
原来在 InputDispatcher 中有一个mLooper会一直poll,当上面的wake执行时会让pollOnce返回,
并执行dispatchOnceInnerLocked.
4.1 InputDispatcher 中的poll
4.2 wake之后执行的函数
在./frameworks/native/libs/utils/Looper.cpp中
1. 新设备的open过程
当扫描到/dev/input/event*设备结点时,会调用下面这个函数
- status_t EventHub::openDeviceLocked(const char *devicePath) {
- int fd = open(devicePath, O_RDWR | O_CLOEXEC);
- ioctl(fd, EVIOCGNAME(sizeof(buffer) - 1), &buffer);
- //用open ioctl与驱动交互将设备的name pid vid写到descriptor中去
- setDescriptor(identifier);
- //顺序产生deviceId
- int32_t deviceId = mNextDeviceId++;
- //新建一个struct Device
- Device* device = new Device(fd, deviceId, String8(devicePath), identifier);
- loadConfigurationLocked(device); //这个load一般都为null
- //获取各个mask
- ioctl(fd, EVIOCGBIT(EV_KEY, sizeof(device->keyBitmask)), device->keyBitmask);
- ioctl(fd, EVIOCGBIT(EV_ABS, sizeof(device->absBitmask)), device->absBitmask);
- ioctl(fd, EVIOCGBIT(EV_REL, sizeof(device->relBitmask)), device->relBitmask);
- ioctl(fd, EVIOCGBIT(EV_SW, sizeof(device->swBitmask)), device->swBitmask);
- ioctl(fd, EVIOCGBIT(EV_LED, sizeof(device->ledBitmask)), device->ledBitmask);
- ioctl(fd, EVIOCGBIT(EV_FF, sizeof(device->ffBitmask)), device->ffBitmask);
- ioctl(fd, EVIOCGPROP(sizeof(device->propBitmask)), device->propBitmask);
- //对mask进行解析,确定classes
- 键盘的classes = 0x61;
- INPUT_DEVICE_CLASS_GAMEPAD|
- INPUT_DEVICE_CLASS_DPAD|
- INPUT_DEVICE_CLASS_KEYBOARD
-
- //键盘与众不同的地方在于,会加载KeyMap
- status_t keyMapStatus = NAME_NOT_FOUND;
- if (device->classes & (INPUT_DEVICE_CLASS_KEYBOARD | INPUT_DEVICE_CLASS_JOYSTICK)) {
- keyMapStatus = loadKeyMapLocked(device);
- }
- //添加到epoll中
- struct epoll_event eventItem;
- memset(&eventItem, 0, sizeof(eventItem));
- eventItem.events = EPOLLIN;
- eventItem.data.u32 = deviceId;
- epoll_ctl(mEpollFd, EPOLL_CTL_ADD, fd, &eventItem);
- //将设备信息保存在全局struct Device数组中.
- addDeviceLocked(device);
- return 0;
- }
在./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
- bool KeyMap::probeKeyMap(const InputDeviceIdentifier& deviceIdentifier, const String8& keyMapName) {
- if (!haveKeyLayout()) { //加载kl文件
- loadKeyLayout(deviceIdentifier, keyMapName);
- }
- if (!haveKeyCharacterMap()) {
- loadKeyCharacterMap(deviceIdentifier, keyMapName);
- }
- return isComplete();
- }
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
- void InputReader::loopOnce()
- {
- //获取event
- size_t count = mEventHub->getEvents(timeoutMillis, mEventBuffer, EVENT_BUFFER_SIZE);
- if (count) {
- processEventsLocked(mEventBuffer, count); //对event进行处理
- }
- mQueuedListener->flush();
- }
--> InputReader::processEventsLocked
- void InputReader::processEventsLocked(const RawEvent* rawEvents, size_t count)
- {
- for (const RawEvent* rawEvent = rawEvents; count;)
- {
- if (type < EventHubInterface::FIRST_SYNTHETIC_EVENT) {
- //数据处理流程
- } else {
- switch (rawEvent->type) {
- case EventHubInterface::DEVICE_ADDED: //新发现的设备的处理
- addDeviceLocked(rawEvent->when, rawEvent->deviceId);
- break;
- case EventHubInterface::DEVICE_REMOVED:
- removeDeviceLocked(rawEvent->when, rawEvent->deviceId);
- break;
- case EventHubInterface::FINISHED_DEVICE_SCAN: //最后会调用这个
- handleConfigurationChangedLocked(rawEvent->when);
- break;
- default:
- ALOG_ASSERT(false); // can't happen
- break;
- }
- }
- }
- }
InputReader::loopOnce
--> InputReader::processEventsLocked
--> InputReader::addDeviceLocked
- 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();
- }
InputReader::loopOnce
--> InputReader::processEventsLocked
--> InputReader::addDeviceLocked
--> InputReader::createDeviceLocked
键盘设备的classes=0x61,mapper添加的是KeyboardInputMapper
- InputDevice* InputReader::createDeviceLocked(int32_t deviceId, const InputDeviceIdentifier& identifier, uint32_t classes)
- {
- InputDevice* device = new InputDevice(&mContext, deviceId, bumpGenerationLocked(), identifier, classes);
- device->addMapper(new KeyboardInputMapper(device, keyboardSource, keyboardType));
- return device;
- }
3.1 数据事件的处理过程
inputreader会收到event
- void InputReader::loopOnce()
- {
- //获取event
- size_t count = mEventHub->getEvents(timeoutMillis, mEventBuffer, EVENT_BUFFER_SIZE);
- if (count) {
- processEventsLocked(mEventBuffer, count); //对event进行处理
- }
- mQueuedListener->flush();
- }
--> InputReader::processEventsLocked ;;区分数据与特殊事件
- void InputReader::processEventsLocked(const RawEvent* rawEvents, size_t count) {
- for (const RawEvent* rawEvent = rawEvents; count;) {
- int32_t type = rawEvent->type;
- size_t batchSize = 1;
- if (type < EventHubInterface::FIRST_SYNTHETIC_EVENT) {
- processEventsForDeviceLocked(deviceId, rawEvent, batchSize); //处理数据事件
- } else {
- //处理特殊事件,如设备添加删除
- }
- count -= batchSize;
- rawEvent += batchSize;
- }
- }
InputReader::loopOnce
--> InputReader::processEventsLocked ;;区分数据与特殊事件
--> InputDevice::process ;;增加数据丢失处理后,用for循环对每个事件进行处理
- 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; //直到下一次数据同步才会改变为false
- }
- } else if (rawEvent->type == EV_SYN && rawEvent->code == SYN_DROPPED) {
- mDropUntilNextSync = true; //所以有数据丢失时是不会进行mapper处理的
- reset(rawEvent->when);
- } else {
- for (size_t i = 0; i < numMappers; i++) {
- InputMapper* mapper = mMappers[i];
- mapper->process(rawEvent);
- }
- }
- }
- }
InputReader::loopOnce
--> InputReader::processEventsLocked ;;区分数据与特殊事件
--> InputDevice::process ;;增加数据丢失处理后,用for循环对每个事件进行处理
--> KeyboardInputMapper::process ;;单件event的数据处理
- void KeyboardInputMapper::process(const RawEvent* rawEvent) {
- switch (rawEvent->type) {
- case EV_KEY: { //只对type=0x01(EV_KEY)的事件进行处理
- //3.2.2 解析映射过程
- if (isKeyboardOrGamepadKey(scanCode)) {
- int32_t keyCode;
- uint32_t flags;
- if (getEventHub()->mapKey(getDeviceId(), scanCode, usageCode, &keyCode, &flags)) {
- keyCode = AKEYCODE_UNKNOWN;
- flags = 0;
- }
- processKey(rawEvent->when, rawEvent->value != 0, keyCode, scanCode, flags);
- }
- break;
- }
- case EV_MSC: //其它的事件只是设个标志位,不关心
- break;
- case EV_SYN:
- break;
- }
- }
例如:/system/usr/keylayout/Generic.kl有如下片断
- key 256 BUTTON_1
- key 257 BUTTON_2
- key 258 BUTTON_3
- key 259 BUTTON_4
- key 260 BUTTON_5
- key 261 BUTTON_6
在./frameworks/native/include/android/keycodes.h中,是标准的android键值.
- AKEYCODE_BUTTON_1 = 188,
- AKEYCODE_BUTTON_2 = 189,
- AKEYCODE_BUTTON_3 = 190,
- AKEYCODE_BUTTON_4 = 191,
- AKEYCODE_BUTTON_5 = 192,
- AKEYCODE_BUTTON_6 = 193,
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);
- void KeyboardInputMapper::processKey(nsecs_t when, bool down, int32_t keyCode,
- int32_t scanCode, uint32_t policyFlags)
- {
- if (down) { //按下状态
- if (mParameters.orientationAware && mParameters.hasAssociatedDisplay)
- keyCode = rotateKeyCode(keyCode, mOrientation); //看来旋转是在这儿处理的,不过此时不关心
-
- ssize_t keyDownIndex = findKeyDown(scanCode);
- if (keyDownIndex >= 0) {
- keyCode = mKeyDowns.itemAt(keyDownIndex).keyCode;
- } else {
- mKeyDowns.push();
- KeyDown& keyDown = mKeyDowns.editTop();
- keyDown.keyCode = keyCode;
- keyDown.scanCode = scanCode;
- }
- mDownTime = when;
- } else {
- ssize_t keyDownIndex = findKeyDown(scanCode);
- if (keyDownIndex >= 0) {
- keyCode = mKeyDowns.itemAt(keyDownIndex).keyCode;
- mKeyDowns.removeAt(size_t(keyDownIndex));
- }
- }
- bool metaStateChanged = false;
- int32_t oldMetaState = mMetaState;
- int32_t newMetaState = updateMetaState(keyCode, down, oldMetaState);
- if (oldMetaState != newMetaState) {
- mMetaState = newMetaState;
- metaStateChanged = true;
- updateLedState(false);
- }
- //上面的没有仔细看
- //这个args,会区分down与up事件
- //这个地方组成一个args,调用notifyKey.
- NotifyKeyArgs args(when, getDeviceId(), mSource, policyFlags,
- down ? AKEY_EVENT_ACTION_DOWN : AKEY_EVENT_ACTION_UP,
- AKEY_EVENT_FLAG_FROM_SYSTEM, keyCode, scanCode, newMetaState, downTime);
- getListener()->notifyKey(&args);
- }
四. inputDispatcher的处理
InputReader::loopOnce
--> InputReader::processEventsLocked ;;区分数据与特殊事件
--> InputDevice::process ;;增加数据丢失处理后,用for循环对每个事件进行处理
--> KeyboardInputMapper::process ;;单件event的数据处理,按type区分事件类型
--> KeyboardInputMapper::processKey ;;只对type=0x01(EV_KEY)处理
--> InputDispatcher::notifyKey
将args重新组装成一个keyEntry并插入到队列中,最后唤醒队列,并进行处理
- void InputDispatcher::notifyKey(const NotifyKeyArgs* args)
- {
- //在因构造函数中会加入EventEntry(TYPE_KEY, eventTime, policyFlags)
- //类型为TYPE_KEY
- KeyEntry* newEntry = new KeyEntry(args->eventTime,
- args->deviceId, args->source, policyFlags,
- args->action, flags, args->keyCode, args->scanCode,
- metaState, repeatCount, args->downTime);
-
- needWake = enqueueInboundEventLocked(newEntry);
- if (needWake) {
- mLooper->wake();
- }
- }
原来在 InputDispatcher 中有一个mLooper会一直poll,当上面的wake执行时会让pollOnce返回,
并执行dispatchOnceInnerLocked.
4.1 InputDispatcher 中的poll
- void InputDispatcher::dispatchOnce()
- {
- nsecs_t nextWakeupTime = LONG_LONG_MAX;
- {
- AutoMutex _l(mLock);
- mDispatcherIsAliveCondition.broadcast();
- if (!haveCommandsLocked()) {
- dispatchOnceInnerLocked(&nextWakeupTime); //当有事件唤醒时就会执行这个函数
- }
- if (runCommandsLockedInterruptible()) {
- nextWakeupTime = LONG_LONG_MIN;
- }
- }
- nsecs_t currentTime = now();
- int timeoutMillis = toMillisecondTimeoutDelay(currentTime, nextWakeupTime);
- mLooper->pollOnce(timeoutMillis); //在这儿等侍事件的发生
- }
- void InputDispatcher::dispatchOnceInnerLocked(nsecs_t* nextWakeupTime)
- {
- case EventEntry::TYPE_KEY:
- done = dispatchKeyLocked(currentTime, typedEntry, &dropReason, nextWakeupTime);
- break;
- }
在./frameworks/native/libs/utils/Looper.cpp中
- void Looper::wake() {
- ssize_t nWrite;
- do {
- nWrite = write(mWakeWritePipeFd, "W", 1); //向管道中写入一个值,然后管道中有数据变化就会唤醒.
- } while (nWrite == -1 && errno == EINTR);
- }