AOSP15 Input专题InputReader源码分析

0 阅读5分钟

在 Android 15 中,InputReader 依然是输入系统(Input System)的核心组件,负责从内核读取原始事件并进行预处理。理解它的调用流程,需要将其放在 InputDispatcher 的上下文中观察。

一、 输入系统的宏观调用流向

输入系统的宏观调用流向 当用户操作屏幕时,事件在内核驱动和用户空间之间流转。

二、 详细调用链路分析 (从内核到 Mapper)

1. 第一步:驱动循环 (InputReader.cpp)

InputReader 运行在一个独立的线程中,其主循环 loopOnce() 不断地询问 EventHub 是否有新数据。

  • 文件: frameworks/native/services/inputflinger/reader/InputReader.cpp

  • 方法分析:

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
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
  • 方法分析:
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(例如:TouchInputMapperKeyboardInputMapper

  • 文件: frameworks/native/services/inputflinger/reader/InputDevice.cpp
  • 方法分析:
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
  • 方法分析:
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
  • 详细步骤:
    1. Normalization: 将内核定义的逻辑坐标归一化。

    2. Transformation: 应用 SurfaceRotation 和 CalibrationMatrix(如坐标偏移、缩放)。

    3. Gesture Generation: 识别是“点按”、“拖动”还是“多指捏合”。

    4. Notify: 调用 getListener().notifyMotion(&args) 将处理好的数据发送给 InputDispatcher。

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;
}

三、总结

  1. EventHub (生产):利用 epoll 监听 /dev/input/,将内核信号封装为 RawEvent。

  2. InputReader (循环):在 loopOnce() 中轮询 EventHub,并将事件分发给对应的物理设备(InputDevice)。

  3. InputDevice (分发):将事件广播给关联的多个 InputMapper(如 TouchInputMapper 处理触控,KeyboardInputMapper 处理按键)。

  4. TouchInputMapper (变换):核心逻辑层。它通过 process() 收集 RawEvent,并在 SYN_REPORT 到达时调用 processRawTouches(),进行坐标归一化、矩阵变换及手势识别。