InputReader线程获取输入事件-Android12
android12-release
InputManagerService启动-Android12
1、InputReader线程启动轮询threadLoop
1.1、threadLoop
frameworks\native\services\inputflinger\reader\InputReader.cpp
status_t InputReader::start() {
if (mThread) {
return ALREADY_EXISTS;
}
mThread = std::make_unique<InputThread>(
"InputReader", [this]() { loopOnce(); }, [this]() { mEventHub->wake(); });
return OK;
}
frameworks\native\services\inputflinger\InputThread.cpp
1.2 InputReader::loopOnce()
mEventHub->getEvents
从EventHub读取事件processEventsLocked
处理事件mQueuedListener->flush()
发送Event到InputDispatcher
2、EventHub::getEvents读取事件/dev/input
frameworks\native\services\inputflinger\reader\EventHub.cpp
scanDevicesLocked()
扫描/dev/input
节点设备read
从设备不断读取事件 input_event 信息到 readBufferRawEvent* event
将 input_event 信息, 封装成 RawEventpollResult = epoll_wait
等待input事件event - buffer
返回我们读取的事件数
EventHub 采用 epoll 机制监听 /dev/input 下的设备节点,将 input_event + deviceId 转换成 RawEvent 结构体,如下:
size_t EventHub::getEvents(int timeoutMillis, RawEvent* buffer, size_t bufferSize) {
ALOG_ASSERT(bufferSize >= 1);
AutoMutex _l(mLock);
struct input_event readBuffer[bufferSize];
RawEvent* event = buffer;
size_t capacity = bufferSize;
bool awoken = false;
for (;;) {
nsecs_t now = systemTime(SYSTEM_TIME_MONOTONIC);
// ... ...
if (mNeedToScanDevices) {
mNeedToScanDevices = false;
scanDevicesLocked();
mNeedToSendFinishedDeviceScan = true;
}
// ... ...
// Grab the next input event.
bool deviceChanged = false;
while (mPendingEventIndex < mPendingEventCount) {
const struct epoll_event& eventItem = mPendingEventItems[mPendingEventIndex++];
// ... ...
// This must be an input event
if (eventItem.events & EPOLLIN) {
int32_t readSize =
read(device->fd, readBuffer, sizeof(struct input_event) * capacity);
if (readSize == 0 || (readSize < 0 && errno == ENODEV)) {
// ... ...
} 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++) {
struct input_event& iev = readBuffer[i];
event->when = processEventTimestamp(iev);
event->deviceId = deviceId;
event->type = iev.type;
event->code = iev.code;
event->value = iev.value;
event += 1;
capacity -= 1;
}
if (capacity == 0) {
// The result buffer is full. Reset the pending event index
// so we will try to read the device again on the next iteration.
mPendingEventIndex -= 1;
break;
}
}
} else if (eventItem.events & EPOLLHUP) {
// ... ...
} else {
// ... ...
}
}
// ... ...
mLock.unlock(); // release lock before poll
int pollResult = epoll_wait(mEpollFd, mPendingEventItems, EPOLL_MAX_EVENTS, timeoutMillis);
mLock.lock(); // reacquire lock after poll
// ... ...
if (pollResult < 0) {
// An error occurred.
mPendingEventCount = 0;
// Sleep after errors to avoid locking up the system.
// Hopefully the error is transient.
if (errno != EINTR) {
ALOGW("poll failed (errno=%d)\n", errno);
usleep(100000);
}
} else {
// Some events occurred.
mPendingEventCount = size_t(pollResult);
}
}
// All done, return the number of events we read.
return event - buffer;
}
2.1、设备扫描scanDevicesLocked
/dev/input/目录下所有的设备节点
static const char* DEVICE_PATH = "/dev/input";
// v4l2 devices go directly into /dev
static const char* VIDEO_DEVICE_PATH = "/dev";
void EventHub::scanDevicesLocked() {
status_t result = scanDirLocked(DEVICE_PATH);
if (result < 0) {
ALOGE("scan dir failed for %s", DEVICE_PATH);
}
if (isV4lScanningEnabled()) {
result = scanVideoDirLocked(VIDEO_DEVICE_PATH);
if (result != OK) {
ALOGE("scan video dir failed for %s", VIDEO_DEVICE_PATH);
}
}
if (mDevices.indexOfKey(ReservedInputDeviceId::VIRTUAL_KEYBOARD_ID) < 0) {
createVirtualKeyboardLocked();
}
}
2.2、RawEvent 结构体
frameworks\native\services\inputflinger\reader\include\EventHub.h
struct RawEvent {
nsecs_t when; //事件发生的时间点
int32_t deviceId; //产生事件的设备Id
int32_t type; //事件类型
int32_t code; //事件 code:input-event-codes.h
int32_t value; //事件值 value
};
3、事件处理processEventsLocked
3.1、addDeviceLocked 添加设备
frameworks\native\services\inputflinger\reader\InputDevice.cpp
最终调用InputDevice::addEventHubDevice;Input设备类型有很多种,其中常见的设备 InputMapper:
- 键盘类设备:
KeyboardInputMapper
- 触摸屏设备:
MultiTouchInputMapper
或SingleTouchInputMapper
- 鼠标类设备:
CursorInputMapper
3.2、事件处理processEventsForDeviceLocked
frameworks\native\services\inputflinger\reader\include\InputDevice.h
frameworks\native\services\inputflinger\reader\InputDevice.cpp
最终调用InputDevice::process,再交由对应的InputMapper
处理,就是上面3.1中提到的,如KeyboardInputMapper
4、mQueuedListener->flush()
frameworks\native\services\inputflinger\include\InputListener.h
frameworks\native\services\inputflinger\InputListener.cpp
这个sp<InputListenerInterface> mInnerListener
是啥玩意呢,一下想不到,回头看到InputReader
初始化就是InputDispatcher
4.1、NotifyArgs
对用多种
NotifyArgs在InputMapper初始化,对用不同的输入,如KeyboardInputMapper
frameworks\native\services\inputflinger\include\InputListener.h
frameworks\native\services\inputflinger\InputListener.cpp
- NotifyKeyArgs
- NotifyMotionArgs
- NotifySwitchArgs
- NotifyDeviceResetArgs
4.2、NotifyArgs.notify
通知到InputDispatcher
mLooper->wake()
唤醒InputDispatcher中InputThread线程
frameworks\native\services\inputflinger\dispatcher\InputDispatcher.cpp
- InputDispatcher::notifyKey
- InputDispatcher::notifyMotion
- InputDispatcher::notifySwitch
- InputDispatcher::notifyDeviceReset