一. EventHub发现设备结点,并对键盘设备加载配置文件
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;
-
}
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
-
bool KeyMap::probeKeyMap(const InputDeviceIdentifier& deviceIdentifier, const String8& keyMapName) {
-
if (!haveKeyLayout()) { //加载kl文件
-
loadKeyLayout(deviceIdentifier, keyMapName);
-
}
-
if (!haveKeyCharacterMap()) {
-
loadKeyCharacterMap(deviceIdentifier, keyMapName);
-
}
-
return isComplete();
-
}
找配置文件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
-
void InputReader::loopOnce()
-
{
-
//获取event
-
size_t count = mEventHub->getEvents(timeoutMillis, mEventBuffer, EVENT_BUFFER_SIZE);
-
if (count) {
-
processEventsLocked(mEventBuffer, count); //对event进行处理
-
}
-
mQueuedListener->flush();
-
}
InputReader::loopOnce
-->
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;
-
}
-
}
-
}
-
}
2.2 设备添加事件的处理
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();
-
}
2.2.1 addMaper
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::loopOnce
-->
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;
-
}
-
}
3.2 接收到数据事件后,调用mapper的process
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);
-
}
-
}
-
}
-
}
3.2.1 mapper的process对单个事件进行处理
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;
-
}
-
}
3.2.2 解析映射过程
例如:/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
当接收到的scanCode=256时,在这个kl中会映射成BUTTON_1,而BUTTON_1又是什么呢?
在./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,
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);
-
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);
-
}
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并插入到队列中,最后唤醒队列,并进行处理
-
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();
-
}
-
}
mLooper->wake这个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); //在这儿等侍事件的发生
-
}
4.2 wake之后执行的函数
-
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);
-
}
阅读(1363) | 评论(0) | 转发(0) |