InputReader

InputReader

input输入系统中,我们使用InputReader来读取底层节点中的数据,并对数据进行处理加工
首先InputReader是运行在线程InputReader上的,我们从他的start方法开始
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;
}

开启一个名为InputReader的线程,主要执行loopOnce这个方法,继续看loopOnce方法,首先通过mEventHub->getEvents获取底层节点数据,再通过processEventsLocked方法解析这些数据。
根据之前介绍的EventHub的逻辑,第一次调用getEvents其实是获取不到输入事件的,这次只是将底层节点加入到epoll的监听上了,当epoll监听到节点可读,将会触发mEventHub->wake,这样就会再次执行这个loopOnce方法第二次调用getEvents来读取相应数据

void InputReader::loopOnce() {
    //通过EventHub读取底层节点数据
    size_t count = mEventHub->getEvents(timeoutMillis, mEventBuffer, EVENT_BUFFER_SIZE);
    //processEventsLocked处理数据
        if (count) {
            processEventsLocked(mEventBuffer, count);
        }
    //刷新QueuedListener
    mQueuedListener->flush();
}

void InputReader::processEventsLocked(const RawEvent* rawEvents, size_t count) {
    for (const RawEvent* rawEvent = rawEvents; count;) {
        int32_t type = rawEvent->type;
        if (type < EventHubInterface::FIRST_SYNTHETIC_EVENT) {
            int32_t deviceId = rawEvent->deviceId;
            //processEventsForDeviceLocked处理一般输入事件
            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); // can't happen
                    break;
            }
        }
    }
}
//调用createDeviceLocked生成一个新的InputDevice,加入mDevices中,eventHubId为key
void InputReader::addDeviceLocked(nsecs_t when, int32_t eventHubId) {
    
    std::shared_ptr<InputDevice> device = createDeviceLocked(eventHubId, identifier);
   
    mDevices.emplace(eventHubId, device);

}

    enum {
        // Sent when a device is added.
        DEVICE_ADDED = 0x10000000,
        // Sent when a device is removed.
        DEVICE_REMOVED = 0x20000000,
        // Sent when all added/removed devices from the most recent scan have been reported.
        // This event is always sent at least once.
        FINISHED_DEVICE_SCAN = 0x30000000,

        FIRST_SYNTHETIC_EVENT = DEVICE_ADDED,
    };
}

loopOnce从底层读取到数据,这些数据包含多种事件类型,processEventsLocked方法根据事件类型进行处理

  • DEVICE_ADDED 新增输入设备,根据读取到的属性生成InputDevice加入到mDevices中
  • DEVICE_REMOVED 移除输入设备,根据deviceId,移除mDevices中的对应InputDevice
  • FINISHED_DEVICE_SCAN 标志扫描事件结束
  • type < FIRST_SYNTHETIC_EVENT 由输入设备产生的事件,我们一般意义上指代的输入事件

InputDevice对象是和底层的节点相对应的,用于描述底层输入设备的相关信息,每个Device对象在生成时,内部都会保存一些InputMapper对象用于处理各自设备节点的输入事件,不同的InputMapper都有各自处理事件的逻辑,比如处理键盘事件的KeyboardInputMapper,处理触摸事件的MultiTouchInputMapper

std::shared_ptr<InputDevice> InputReader::createDeviceLocked({

    std::shared_ptr<InputDevice> device;
    device = std::make_shared<InputDevice>(&mContext, deviceId, bumpGenerationLocked(), identifier);}
    device->addEventHubDevice(eventHubId);
    return device;
}

void InputDevice::addEventHubDevice(int32_t eventHubId, bool populateMappers) {
   
    std::vector<std::unique_ptr<InputMapper>> mappers;

    // 根据InputDevice的不同属性添加相应的InputMapper到mappers中,这里就加了一个KeyboardInputMapper和MultiTouchInputMapper
    if (keyboardSource != 0) {
        mappers.push_back(
                std::make_unique<KeyboardInputMapper>(*contextPtr, keyboardSource, keyboardType));
    }
    if (classes & INPUT_DEVICE_CLASS_TOUCH_MT) {
  mappers.push_back(std::make_unique<MultiTouchInputMapper>(*contextPtr));
    } else if (classes & INPUT_DEVICE_CLASS_TOUCH) { mappers.push_back(std::make_unique<SingleTouchInputMapper>(*contextPtr));
    }

对于一般输入事件,调用processEventsForDeviceLocked方法处理,就是调用这些InputDevice去处理原始事件数据的

void InputReader::processEventsForDeviceLocked(int32_t eventHubId, const RawEvent* rawEvents,
                                               size_t count) {
    //通过key查找到对应的InputDevice
    auto deviceIt = mDevices.find(eventHubId);
    std::shared_ptr<InputDevice>& device = deviceIt->second;
    //调用InputDevice的process方法处理原始事件数据
    device->process(rawEvents, count);
}

void InputDevice::process(const RawEvent* rawEvents,, size_t count) {
    ...
    //遍历rawEvents,通过mappers中的InputMapper处理
    for (const RawEvent* rawEvent = rawEvents; count != 0; rawEvent++) {
        ...
        for_each_mapper_in_subdevice(rawEvent->deviceId, [rawEvent](InputMapper& mapper) {
            mapper.process(rawEvent);
            });
        }
    }
}

void KeyboardInputMapper::process(const RawEvent* rawEvent) {
    switch (rawEvent->type) {
        case EV_KEY: {
            int32_t scanCode = rawEvent->code;
            //判断是否是键盘事件
            if (isKeyboardOrGamepadKey(scanCode)) {
                processKey(rawEvent->when, rawEvent->value != 0, scanCode, usageCode);
            }
            break;
        }
    }
}

void KeyboardInputMapper::processKey(nsecs_t when, bool down, int32_t scanCode, int32_t usageCode) {
    ...
    //封装NotifyKeyArgs对象,传递出去
    NotifyKeyArgs args(getContext()->getNextId(), when, getDeviceId(), mSource, getDisplayId(),
                       policyFlags, down ? AKEY_EVENT_ACTION_DOWN : AKEY_EVENT_ACTION_UP,
                       AKEY_EVENT_FLAG_FROM_SYSTEM, keyCode, scanCode, keyMetaState, downTime);
    getListener()->notifyKey(&args);
}

NotifyKeyArgs继承自NotifyArgs。
processEventsForDeviceLocked处理Key事件逻辑

  • 通过eventHubId从mDevices中查找到对应的InputDevice
  • InputDevice.process->KeyboardInputMapper.process->KeyboardInputMapper.processKey->getListener()->notifyKey
  • mQueuedListener->flush()将事件传递出去
void QueuedInputListener::notifyKey(const NotifyKeyArgs* args) {
    //将封装好的NotifyKeyArgs放入到mArgsQueue
    mArgsQueue.push_back(new NotifyKeyArgs(*args));
}

void QueuedInputListener::flush() {
    //取出所有NotifyArgs对象,执行notify方法
    size_t count = mArgsQueue.size();
    for (size_t i = 0; i < count; i++) {
        NotifyArgs* args = mArgsQueue[i];
        args->notify(mInnerListener);
        delete args;
    }
    mArgsQueue.clear();
}

执行了mArgsQueue.push操作将NotifyKeyArgs放进队列中。在flush时取出来执行NotifyArgs的notify方法,notify代码如下

void NotifyKeyArgs::notify(const sp<InputListenerInterface>& listener) const {
    listener->notifyKey(this);
}

这里调用传递进来的listener执行notifyKey方法,而InputDispatcher继承了InputListenerInterface,这里最终调用了的其实就是InputDispatcher中的notifyKey函数。
此时事件已经成功从InputReader传递到InputDispatcher了
在这里插入图片描述

由上面我们分析可知,只有被InputMapper识别的事件才能传输到InputDispatcher中,即一般事件的流程图如下:

在这里插入图片描述

Touch触摸事件逻辑类似,调用MultiTouchInputMapper,封装NotifyMotionArgs对象进行处理的,所有的事件最终通过QueuedInputListener.flush触发发送到InputDispatcher的notifyMotion函数

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值