前言

前面其实也有提到EventHub的构造函数,里面就是创建epoll实例,然后把一些事件触发的文件描述符加入到epoll里面统一管理。

  • 监控/dev/input/目录的iNotify文件mINotifyFd
  • 接收Kernel驱动事件(/dev/input/eventX)的文件描述符
  • 用来唤醒InputReader线程的管道读文件

EventHub是服务于InputReader线程的,前面在InputRead的构造函数里面有创建EventHub的实例。

InputReader线程

InputReader线程主要就是查看threadLoop接口中代码的实现,threadLoop返回值是true代表的是会不断的循环,返回false的话就不会继续在调用threadLoop函数。

1
2
3
4
bool InputReaderThread::threadLoop() {
mReader->loopOnce();
return true;
}

不停的调用InputReaderloopOnce函数

loopOnce函数

InputReader.cpp

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
void InputReader::loopOnce() {
...
{
AutoMutex _l(mLock);
uint32_t changes = mConfigurationChangesToRefresh;
if (changes) {
timeoutMillis = 0;
...
} else if (mNextTimeout != LLONG_MAX) {
nsecs_t now = systemTime(SYSTEM_TIME_MONOTONIC);
timeoutMillis = toMillisecondTimeoutDelay(now, mNextTimeout);
}
}

//从EventHub读取事件,其中EVENT_BUFFER_SIZE = 256
size_t count = mEventHub->getEvents(timeoutMillis, mEventBuffer, EVENT_BUFFER_SIZE);

{ // acquire lock
AutoMutex _l(mLock);
mReaderIsAliveCondition.broadcast();
if (count) { //处理事件
processEventsLocked(mEventBuffer, count);
}
if (oldGeneration != mGeneration) {
inputDevicesChanged = true;
getInputDevicesLocked(inputDevices);
}
...
} // release lock


if (inputDevicesChanged) { //输入设备发生改变
mPolicy->notifyInputDevicesChanged(inputDevices);
}
//发送事件到nputDispatcher
mQueuedListener->flush();
}

两个关键的地方,从注释可以很明确的看出来,首先是获取到底层的input事件,处理事件,然后发送到InputDispatcher线程

  • mEventHub->getEvents
  • processEventsLocked(mEventBuffer, count)
  • mQueuedListener->flush
EventHub->getEvents

EventHub.cpp

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
size_t EventHub::getEvents(int timeoutMillis, RawEvent* buffer, size_t bufferSize) {
AutoMutex _l(mLock); //加锁

struct input_event readBuffer[bufferSize];
RawEvent* event = buffer; //原始事件
size_t capacity = bufferSize; //容量大小为256
bool awoken = false;
for (;;) {
nsecs_t now = systemTime(SYSTEM_TIME_MONOTONIC);
...

if (mNeedToScanDevices) {
mNeedToScanDevices = false;
scanDevicesLocked(); //扫描设备
mNeedToSendFinishedDeviceScan = true;
}

while (mOpeningDevices != NULL) {
Device* device = mOpeningDevices;
mOpeningDevices = device->next;
event->when = now;
event->deviceId = device->id == mBuiltInKeyboardId ? 0 : device->id;
event->type = DEVICE_ADDED; //添加设备的事件
event += 1;
mNeedToSendFinishedDeviceScan = true;
if (--capacity == 0) {
break;
}
}
...

bool deviceChanged = false;
while (mPendingEventIndex < mPendingEventCount) {
//从mPendingEventItems读取事件项
const struct epoll_event& eventItem = mPendingEventItems[mPendingEventIndex++];
...
//获取设备ID所对应的device
ssize_t deviceIndex = mDevices.indexOfKey(eventItem.data.u32);
Device* device = mDevices.valueAt(deviceIndex);
if (eventItem.events & EPOLLIN) {
//从设备不断读取事件,放入到readBuffer
int32_t readSize = read(device->fd, readBuffer,
sizeof(struct input_event) * capacity);

if (readSize == 0 || (readSize < 0 && errno == ENODEV)) {
deviceChanged = true;
closeDeviceLocked(device);//设备已被移除则执行关闭操作
} else if (readSize < 0) {
...
} else if ((readSize % sizeof(struct input_event)) != 0) {
...
} else {
int32_t deviceId = device->id == mBuiltInKeyboardId ? 0 : device->id;
size_t count = size_t(readSize) / sizeof(struct input_event);

for (size_t i = 0; i < count; i++) {
//获取readBuffer的数据
struct input_event& iev = readBuffer[i];
//将input_event信息, 封装成RawEvent
event->when = nsecs_t(iev.time.tv_sec) * 1000000000LL
+ nsecs_t(iev.time.tv_usec) * 1000LL;
event->deviceId = deviceId;
event->type = iev.type;
event->code = iev.code;
event->value = iev.value;
event += 1;
capacity -= 1;
}
if (capacity == 0) {
mPendingEventIndex -= 1;
break;
}
}
}
...
}
...
mLock.unlock(); //poll之前先释放锁
//等待input事件的到来
int pollResult = epoll_wait(mEpollFd, mPendingEventItems, EPOLL_MAX_EVENTS, timeoutMillis);
...
mLock.lock(); //poll之后再次请求锁

if (pollResult < 0) { //出现错误
mPendingEventCount = 0;
if (errno != EINTR) {
usleep(100000); //系统发生错误则休眠1s
}
} else {
mPendingEventCount = size_t(pollResult);
}
}

return event - buffer; //返回所读取的事件个数
}

虽然精简了代码还是比较长,主要是以下几点:

  • EventHub是采用了INotify和epoll机制监听目录/dev/input下设备节点,当有IO事件,会通过epoll_wait返回事件的详细信息
  • 当epoll_wait被返回有IO数据的时候,通过read函数读取input事件的数据
  • 把input_event结构体转化为RawEvent事件

InputEventReader.h

1
2
3
4
5
6
7
8
9
10
11
12
13
14
struct input_event {
struct timeval time; //事件发生的时间点
__u16 type;
__u16 code;
__s32 value;
};

struct RawEvent {
nsecs_t when; //事件发生的时间店
int32_t deviceId; //产生事件的设备Id
int32_t type; // 事件类型
int32_t code;
int32_t value;
};

事件类型:

  1. DEVICE_ADD
  2. DEVICE_REMOVED
  3. FINISHED_DEVICE_SCAN
  4. type
InputReader->processEventsLocked

InputReader.cpp

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
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) {
int32_t deviceId = rawEvent->deviceId;
while (batchSize < count) {
if (rawEvent[batchSize].type >= EventHubInterface::FIRST_SYNTHETIC_EVENT
|| rawEvent[batchSize].deviceId != deviceId) {
break;
}
batchSize += 1; //同一设备的事件打包处理
}
//数据事件的处理
processEventsForDeviceLocked(deviceId, rawEvent, batchSize);
} 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);//不会发生
break;
}
}
count -= batchSize;
rawEvent += batchSize;
}
}

主要是根据不同的事件类型做不同的处理,我们比较关注对数据的处理,主要是看这个函数processEventsForDeviceLocked

事件处理 processEventsForDeviceLocked
1
2
3
4
5
6
7
8
9
10
11
12
void InputReader::processEventsForDeviceLocked(int32_t deviceId,
const RawEvent* rawEvents, size_t count) {
ssize_t deviceIndex = mDevices.indexOfKey(deviceId);
...

InputDevice* device = mDevices.valueAt(deviceIndex);
if (device->isIgnored()) {
return; //可忽略则直接返回
}
//调用对应设备的process函数
device->process(rawEvents, count);
}

通过deviceId来获取合适的InputDeviceInputDevice是当检测到/dev/input/下有设备节点添加的时候创建的

调用对应的device的process函数

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
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来处理
mapper->process(rawEvent);
}
}
}
}

这里处理输入事件主要是把Linux下发送过来的RawEvent转化为Android 的Key Event和Key Code,在Android中不同的输入设备对应不同的Key Layout文件,这里就是选择对应的kl文件来处理。

下面专门针对按键的事件处理跟一下流程。

按键事件处理流程

InputReader.cpp

KeyBoardInputMapper->process

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
void KeyboardInputMapper::process(const RawEvent* rawEvent) {
switch (rawEvent->type) {
case EV_KEY: {
int32_t scanCode = rawEvent->code;
int32_t usageCode = mCurrentHidUsage;
mCurrentHidUsage = 0;

if (isKeyboardOrGamepadKey(scanCode)) {
int32_t keyCode;
//获取所对应的KeyCode
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: ...
case EV_SYN: ...
}
}

通过mapKey函数获取对应scanCode的Android Key Code

EventHub.cpp

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
status_t EventHub::mapKey(int32_t deviceId,
int32_t scanCode, int32_t usageCode, int32_t metaState,
int32_t* outKeycode, int32_t* outMetaState, uint32_t* outFlags) const {
AutoMutex _l(mLock);
Device* device = getDeviceLocked(deviceId); //获取设备对象
status_t status = NAME_NOT_FOUND;

if (device) {
sp<KeyCharacterMap> kcm = device->getKeyCharacterMap();
if (kcm != NULL) {
//根据scanCode找到keyCode
if (!kcm->mapKey(scanCode, usageCode, outKeycode)) {
*outFlags = 0;
status = NO_ERROR;
}
}
}
...
return status;
}

真正干活做转换的是KeyCharacterMap::mapKey函数。

InputReader.cpp

InputMapper->processKey

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
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) {
//mKeyDowns记录着所有按下的键
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));
} else {
return; //键盘没有按下操作,则直接忽略抬起操作
}
}
nsecs_t downTime = mDownTime;
...

//创建NotifyKeyArgs对象, when记录eventTime, downTime记录按下时间;
NotifyKeyArgs args(when, getDeviceId(), mSource, policyFlags,
down ? AKEY_EVENT_ACTION_DOWN : AKEY_EVENT_ACTION_UP,
AKEY_EVENT_FLAG_FROM_SYSTEM, keyCode, scanCode, newMetaState, downTime);
//通知key事件
getListener()->notifyKey(&args);
}
  • mKeyDowns记录着所有按下的键
  • mDownTime记录按下时间点
  • KeyboardInputMappermContext指向InputReadergetListener()获取mQueuedListener,然后调用notifyKey接口

InputListener.cpp

1
2
3
void QueuedInputListener::notifyKey(const NotifyKeyArgs* args) {
mArgsQueue.push(new NotifyKeyArgs(*args));
}

把事件放入向量mArgsQueue,然后就是把事件发送给InputDispatcher线程了

发送事件 QueuedInputListener->flush

InputListener.cpp

1
2
3
4
5
6
7
8
9
10
void QueuedInputListener::flush() {
size_t count = mArgsQueue.size();
for (size_t i = 0; i < count; i++) {
NotifyArgs* args = mArgsQueue[i];
//
args->notify(mInnerListener);
delete args;
}
mArgsQueue.clear();
}

遍历刚才的向量,调用对应的notify接口,NotifyArgs的实现子类包含:

  • NotifyConfigurationChangedArgs
  • NotifyKeyArgs
  • NotifyMotionArgs
  • NotifySwitchArgs
  • NotifyDeviceResetArgs
1
2
3
void NotifyKeyArgs::notify(const sp<InputListenerInterface>& listener) const {
listener->notifyKey(this); // this是指NotifyKeyArgs
}

InputDispatcher.cpp

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
void InputDispatcher::notifyKey(const NotifyKeyArgs* args) {
if (!validateKeyEvent(args->action)) {
return;
}
...
int32_t keyCode = args->keyCode;

if (keyCode == AKEYCODE_HOME) {
if (args->action == AKEY_EVENT_ACTION_DOWN) {
property_set("sys.domekey.down", "1");
} else if (args->action == AKEY_EVENT_ACTION_UP) {
property_set("sys.domekey.down", "0");
}
}

if (metaState & AMETA_META_ON && args->action == AKEY_EVENT_ACTION_DOWN) {
...
} else if (args->action == AKEY_EVENT_ACTION_UP) {
...
}

KeyEvent event; //初始化KeyEvent对象
event.initialize(args->deviceId, args->source, args->action,
flags, keyCode, args->scanCode, metaState, 0,
args->downTime, args->eventTime);
//mPolicy是指NativeInputManager对象。
mPolicy->interceptKeyBeforeQueueing(&event, /*byref*/ policyFlags);

bool needWake;
{
mLock.lock();
if (shouldSendKeyToInputFilterLocked(args)) {
mLock.unlock();
policyFlags |= POLICY_FLAG_FILTERED;
//当inputEventObj不为空, 则事件被filter所拦截
if (!mPolicy->filterInputEvent(&event, policyFlags)) {
return;
}
mLock.lock();
}

int32_t repeatCount = 0;
//创建KeyEntry对象
KeyEntry* newEntry = new KeyEntry(args->eventTime,
args->deviceId, args->source, policyFlags,
args->action, flags, keyCode, args->scanCode,
metaState, repeatCount, args->downTime);
//将KeyEntry放入队列
needWake = enqueueInboundEventLocked(newEntry);
mLock.unlock();
}

if (needWake) {
//唤醒InputDispatcher线程
mLooper->wake();
}
}

主要完成以下几个事情:

  • 调用NativeInputManager.interceptKeyBeforeQueueing,加入队列前执行拦截动作,但并不改变流程
    • IMS.interceptKeyBeforeQueueing
    • InputMonitor.interceptKeyBeforeQueueing(继承IMS.WindowManagerCallbacks
    • PhoneWindowManager.interceptKeyBeforeQueueing(继承WindowManagerPolicy
  • mInputFilterEnabled=true(该值默认为false,可通过setInputFilterEnabled设置),则调用NativeInputManager.filterInputEvent过滤输入事件
    • ​ 当返回值为false则过滤事件,不往下发
  • 生成KeyEvent,并调用enqueueInboundEventLocked,把事件加入到InputDispatchered的成员变量mInboundQueue
  • 唤醒InputDispatcher线程
1
2
3
4
5
6
7
8
9
10
void Looper::wake() {
uint64_t inc = 1;

ssize_t nWrite = TEMP_FAILURE_RETRY(write(mWakeEventFd, &inc, sizeof(uint64_t)));
if (nWrite != sizeof(uint64_t)) {
if (errno != EAGAIN) {
ALOGW("Could not write wake signal, errno=%d", errno);
}
}
}

InputDispatcher线程主要是用来跟JAVA层的IMS和WMS通信的,给JAVA层IMS上报输入事件,找到对应的Window。