在 Android 15 中,InputReader 依然是输入系统(Input System)的核心组件,负责从内核读取原始事件并进行预处理。理解它的调用流程,需要将其放在 InputDispatcher 的上下文中观察。
一、 输入系统的宏观调用流向
输入系统的宏观调用流向 当用户操作屏幕时,事件在内核驱动和用户空间之间流转。

二、 详细调用链路分析 (从内核到 Mapper)
1. 第一步:驱动循环 (InputReader.cpp)
InputReader 运行在一个独立的线程中,其主循环 loopOnce() 不断地询问 EventHub 是否有新数据。
-
文件: frameworks/native/services/inputflinger/reader/InputReader.cpp
-
方法分析:
c++
void InputReader::loopOnce() {
// 省略代码
// 1. 获取内核事件
std::vector<RawEvent> events = mEventHub->getEvents(timeoutMillis);
{
// 省略代码
if (!events.empty()) {
// 2. 遍历事件并分发
mPendingArgs += processEventsLocked(events.data(), events.size());
}
}
// 省略代码
}
2. 获取事件 (Get Events)
调用 EventHub::getEvents()。这是阻塞操作,直到内核有新输入(触控、按键等)
- 文件: frameworks/native/services/inputflinger/reader/EventHub.cpp
c++
std::vector<RawEvent> EventHub::getEvents(int timeoutMillis) {
std::scoped_lock _l(mLock);
std::array<input_event, EVENT_BUFFER_SIZE> readBuffer;
std::vector<RawEvent> events;
bool awoken = false;
for (;;) {
nsecs_t now = systemTime(SYSTEM_TIME_MONOTONIC);
//省略部分
if (mNeedToScanDevices) {
mNeedToScanDevices = false;
scanDevicesLocked();
}
//第一次一般遍历mOpeningDevices这个列表进行各个device获取变成DEVICE_ADDED
while (!mOpeningDevices.empty()) {
std::unique_ptr<Device> device = std::move(*mOpeningDevices.rbegin());
mOpeningDevices.pop_back();
ALOGV("Reporting device opened: id=%d, name=%s\n", device->id, device->path.c_str());
const int32_t deviceId = device->id == mBuiltInKeyboardId ? 0 : device->id;
events.push_back({
.when = now,
.deviceId = deviceId,
.type = DEVICE_ADDED,
});
//省略部分
}
//第一次扫描时候没有消息,指导后面有触摸消息才会进入这里,这里是会由下面epoll监听消息触发
bool deviceChanged = false;
while (mPendingEventIndex < mPendingEventCount) {
const struct epoll_event& eventItem = mPendingEventItems[mPendingEventIndex++];
if (eventItem.data.fd == mINotifyFd) {
if (eventItem.events & EPOLLIN) {
mPendingINotify = true;
} else {
ALOGW("Received unexpected epoll event 0x%08x for INotify.", eventItem.events);
}
continue;
}
if (eventItem.data.fd == mWakeReadPipeFd) {
if (eventItem.events & EPOLLIN) {
ALOGV("awoken after wake()");
awoken = true;
char wakeReadBuffer[16];
ssize_t nRead;
do {
nRead = read(mWakeReadPipeFd, wakeReadBuffer, sizeof(wakeReadBuffer));
} while ((nRead == -1 && errno == EINTR) || nRead == sizeof(wakeReadBuffer));
} else {
ALOGW("Received unexpected epoll event 0x%08x for wake read pipe.",
eventItem.events);
}
continue;
}
Device* device = getDeviceByFdLocked(eventItem.data.fd);
//省略部分
if (eventItem.events & EPOLLIN) {
// 读取对应数据
int32_t readSize =
read(device->fd, readBuffer.data(),
sizeof(decltype(readBuffer)::value_type) * readBuffer.size());
if (readSize == 0 || (readSize < 0 && errno == ENODEV)) {
// Device was removed before INotify noticed.
ALOGW("could not get event, removed? (fd: %d size: %" PRId32
" capacity: %zu errno: %d)\n",
device->fd, readSize, readBuffer.size(), errno);
deviceChanged = true;
closeDeviceLocked(*device);
} else if (readSize < 0) {
if (errno != EAGAIN && errno != EINTR) {
ALOGW("could not get event (errno=%d)", errno);
}
} else if ((readSize % sizeof(struct input_event)) != 0) {
ALOGE("could not get event (wrong size: %d)", readSize);
} else {
const int32_t deviceId = device->id == mBuiltInKeyboardId ? 0 : device->id;
//获取真实读取到的inputevent数据真实个数
const size_t count = size_t(readSize) / sizeof(struct input_event);
for (size_t i = 0; i < count; i++) {
struct input_event& iev = readBuffer[i];
device->trackInputEvent(iev);
events.push_back({
.when = processEventTimestamp(iev),
.readTime = systemTime(SYSTEM_TIME_MONOTONIC),
.deviceId = deviceId,
.type = iev.type,
.code = iev.code,
.value = iev.value,
});
}
//省略部分
}
} else if (eventItem.events & EPOLLHUP) {
ALOGI("Removing device %s due to epoll hang-up event.",
device->identifier.name.c_str());
deviceChanged = true;
closeDeviceLocked(*device);
} else {
// 省略部分
}
}
// 省略部分
//这里epoll在等待消息产生,产生消息EventItem都会放到mPendingEventItems中
int pollResult = epoll_wait(mEpollFd, mPendingEventItems, EPOLL_MAX_EVENTS, timeoutMillis);
mLock.lock(); // reacquire lock after poll
if (pollResult == 0) {
// Timed out.
mPendingEventCount = 0;
break;
}
if (pollResult < 0) {
// 省略部分
} else {
// 这里对mPendingEventCount进行赋值真正有多少个事件产生
mPendingEventCount = size_t(pollResult);
}
}
return events;
}
3. 设备查找 (InputReader.cpp)
processEventsLocked->processEventsForDeviceLocked 会根据 RawEvent 中的 deviceId 找到对应的 InputDevice 对象
- 文件: frameworks/native/services/inputflinger/reader/InputReader.cpp
- 方法分析:
c++
std::list<NotifyArgs> InputReader::processEventsForDeviceLocked(int32_t eventHubId,
const RawEvent* rawEvents,
size_t count) {
auto deviceIt = mDevices.find(eventHubId);
if (deviceIt == mDevices.end()) {
ALOGW("Discarding event for unknown eventHubId %d.", eventHubId);
return {};
}
// 通过 deviceId 查找设备
std::shared_ptr<InputDevice>& device = deviceIt->second;
if (device->isIgnored()) {
// ALOGD("Discarding event for ignored deviceId %d.", deviceId);
return {};
}
// 关键点:调用设备的 process 方法
return device->process(rawEvents, count);
}
4. 分发至 Mapper (InputDevice.cpp)
InputDevice 充当了"管家"的角色。它内部维护了一组 InputMapper。当收到一个 RawEvent 时,它会将该事件广播给所有在该设备上注册的 Mapper(例如:TouchInputMapper、KeyboardInputMapper)
- 文件: frameworks/native/services/inputflinger/reader/InputDevice.cpp
- 方法分析:
c++
std::list<NotifyArgs> InputDevice::process(const RawEvent* rawEvents, size_t count) {
std::list<NotifyArgs> out;
for (const RawEvent* rawEvent = rawEvents; count != 0; rawEvent++) {
if (debugRawEvents()) {
const auto [type, code, value] =
InputEventLookup::getLinuxEvdevLabel(rawEvent->type, rawEvent->code,
rawEvent->value);
}
if (mDropUntilNextSync) {
if (rawEvent->type == EV_SYN && rawEvent->code == SYN_REPORT) {
out += reset(rawEvent->when);
mDropUntilNextSync = false;
} else {
}
} else if (rawEvent->type == EV_SYN && rawEvent->code == SYN_DROPPED) {
mDropUntilNextSync = true;
} else {
// 调用每个 Mapper 的 process 方法
for_each_mapper_in_subdevice(rawEvent->deviceId, [&](InputMapper& mapper) {
out += mapper.process(*rawEvent);
});
}
--count;
}
postProcess(out);
return out;
}
5. 具体 Mapper 处理 (TouchInputMapper.cpp)
这里就是你寻找的地方。TouchInputMapper 接收到原始事件后,会解析该事件并将其填充到 mCurrentRawState 结构体中。
- 文件: frameworks/native/services/inputflinger/reader/mapper/TouchInputMapper.cpp
- 方法分析:
c++
std::list<NotifyArgs> TouchInputMapper::process(const RawEvent& rawEvent) {
// 更新触摸坐标、压力值等
mCursorButtonAccumulator.process(rawEvent);
mCursorScrollAccumulator.process(rawEvent);
mTouchButtonAccumulator.process(rawEvent);
std::list<NotifyArgs> out;
// 当遇到 SYN_REPORT 时,标志着一个完整事件帧的结束
if (rawEvent.type == EV_SYN && rawEvent.code == SYN_REPORT) {
out += sync(rawEvent.when, rawEvent.readTime);
}
return out;
}
6. 坐标转换与分发:TouchInputMapper::processRawTouches()
这里就是你寻找的地方。TouchInputMapper 接收到原始事件后,会解析该事件并将其填充到 mCurrentRawState 结构体中。
- 文件: frameworks/native/services/inputflinger/reader/mapper/touch/TouchInputMapper.cpp
- 详细步骤:
-
Normalization: 将内核定义的逻辑坐标归一化。
-
Transformation: 应用 SurfaceRotation 和 CalibrationMatrix(如坐标偏移、缩放)。
-
Gesture Generation: 识别是"点按"、"拖动"还是"多指捏合"。
-
Notify: 调用 getListener().notifyMotion(&args) 将处理好的数据发送给 InputDispatcher。
-
c++
bool InputReader::gDisable = false;
std::list<NotifyArgs> TouchInputMapper::processRawTouches(bool timeout) {
std::list<NotifyArgs> out;
// InputReader::gDisable 全局输入开关(调试/系统控制)
// mDeviceMode == DISABLED 当前设备被逻辑禁用
if (InputReader::gDisable || mDeviceMode == DeviceMode::DISABLED) {
return out;
}
// Drain Raw 队列(真正的核心循环)
const size_t N = mRawStatesPending.size();
size_t count;
for (count = 0; count < N; count++) {
const RawState& next = mRawStatesPending[count];
if (assignExternalStylusId(next, timeout)) {
break;
}
// All ready to go.
clearStylusDataPendingFlags();
mCurrentRawState = next;
if (mCurrentRawState.when < mLastRawState.when) {
mCurrentRawState.when = mLastRawState.when;
mCurrentRawState.readTime = mLastRawState.readTime;
}
// 真正的转换 + 分发
out += cookAndDispatch(mCurrentRawState.when, mCurrentRawState.readTime);
}
if (count != 0) {
// 处理完成后清理队列
mRawStatesPending.erase(mRawStatesPending.begin(), mRawStatesPending.begin() + count);
}
if (mExternalStylusDataPending) {
if (timeout) {
nsecs_t when = mExternalStylusFusionTimeout - STYLUS_DATA_LATENCY;
clearStylusDataPendingFlags();
mCurrentRawState = mLastRawState;
ALOGD_IF(DEBUG_STYLUS_FUSION,
"Timeout expired, synthesizing event with new stylus data");
const nsecs_t readTime = when;
// 真正的转换 + 分发
out += cookAndDispatch(when, readTime);
} else if (mExternalStylusFusionTimeout == LLONG_MAX) {
mExternalStylusFusionTimeout = mExternalStylusState.when + TOUCH_DATA_TIMEOUT;
getContext()->requestTimeoutAtTime(mExternalStylusFusionTimeout);
}
}
return out;
}
三、总结
-
EventHub(生产):利用 epoll 监听 /dev/input/,将内核信号封装为 RawEvent。 -
InputReader(循环):在 loopOnce() 中轮询 EventHub,并将事件分发给对应的物理设备(InputDevice)。 -
InputDevice(分发):将事件广播给关联的多个 InputMapper(如 TouchInputMapper 处理触控,KeyboardInputMapper 处理按键)。 -
TouchInputMapper(变换):核心逻辑层。它通过 process() 收集 RawEvent,并在 SYN_REPORT 到达时调用 processRawTouches(),进行坐标归一化、矩阵变换及手势识别。