Android 12系统源码_输入系统(三)输入事件的加工和分发

前言

上一篇文章我们具体分析了InputManagerService的构造方法和start方法,知道IMS的start方法经过层层调用,最终会触发Navite层InputDispatcher的start方法和InputReader的start方法。InputDispatcher的start方法会启动一个名为InputDispatcher的线程,该线程会循环调用自己的dispatchOnce方法;InputReader的start方法会启动一个名为InputReader的线程,该线程会循环调用自己的loopOnce方法;并绘制了一个简单的IMS架构图。
在这里插入图片描述
本篇文章我们将在此基础上,继续结合Navite层的InputDispatcher和InputReader的源码,来分析Android系统是如何对输入事件进行加工和分发的。

一、输入事件的加工

1.1 InputReader的start方法

>frameworks/>native/services/inputflinger/reader/InputReader.cpp
status_t InputReader::start() {
   
    
    
    if (mThread) {
   
    
    
        return ALREADY_EXISTS;
    }
    //开启InputThread线程,并循环调用loopOnce方法。
    mThread = std::make_unique<InputThread>(
            "InputReader", [this]() {
   
    
     loopOnce(); }, [this]() {
   
    
     mEventHub->wake(); });
    return OK;
}

void InputReader::loopOnce() {
   
    
    
	 ...代码省略...
	//从事件缓冲区中获取设备节点的事件信息并将其存放到mEventBuffer中
    size_t count = mEventHub->getEvents(timeoutMillis, mEventBuffer, EVENT_BUFFER_SIZE);
	 ...代码省略...
     if (count) {
   
    
    
         //如果有事件,则调用processEventsLocked方法处理这些事件。
         processEventsLocked(mEventBuffer, count);
     }
     ...代码省略...
}

InputReader的start方法会开启一个名为InputThread的线程,该线程会循环调用loopOnce方法,该方法先是从事件缓冲区中获取设备节点的事件信息并将其存放到mEventBuffer中,如果有事件,则调用processEventsLocked方法处理这些事件。

1.2 InputReader的processEventsLocked方法

>frameworks/>native/services/inputflinger/reader/InputReader.cpp

void InputReader::processEventsLocked(const RawEvent* rawEvents, size_t count) {
   
    
    
    //注释1,遍历所有事件
    for (const RawEvent* rawEvent = rawEvents; count;) {
   
    
    
        int32_t type = rawEvent->type;
        size_t batchSize = 1;
        //注释2,事件类型分为原始输入事件和设备事件,这个条件语句对原始输入事件进行处理
        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;
            }
            //处理deviceId所对应设备的原始输入事件
            processEventsForDeviceLocked(deviceId, rawEvent, batchSize);
        } else {
   
    
    
            //注释3,对设备事件进行处理
            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;
            }
        }
        count -= batchSize;
        rawEvent += batchSize;
    }
   

在注释1处会对传递进来的所有事件进行遍历。在注释2处会判断事件是输入事件还是设备事件,如果是输入事件,会调用processEventsForDeviceLocked方法。在注释3处判断如果是事件是设备事件,则会进一步判断设备事件的具体类型,针对不同的事件类型进行不同的操作,如果是设备新增,则调用addDeviceLocked方法,如果是设备移除,则调用removeDeviceLocked,如果配置变化,则调用handleConfigurationChangedLocked方法。

1.2.1 InputReader的processEventsForDeviceLocked方法

>frameworks/>native/services/inputflinger/reader/InputReader.cpp
//处理同一个设备的输入事件
void InputReader::processEventsForDeviceLocked(int32_t eventHubId, const RawEvent* rawEvents,
                                               size_t count) {
   
    
    
    //注释1,通过设备id获取设备对象                                           
    auto deviceIt = mDevices.find(eventHubId);
    if (deviceIt == mDevices.end()) {
   
    
    
        ALOGW("Discarding event for unknown eventHubId %d.", eventHubId);
        return;
    }
    std::shared_ptr<InputDevice>& device = deviceIt->second;//获取输入设备对象
    if (device->isIgnored()) {
   
    
    
        // ALOGD("Discarding event for ignored deviceId %d.", deviceId);
        return;
    }
    //注释,2,调用InputDevices的process方法
    device->process(rawEvents, count);
}

>frameworks/native/services/inputflinger/reader/InputDevice.cpp
void InputDevice::process(const RawEvent* rawEvents, size_t count) {
   
    
    
	//遍历输入事件
    for (const RawEvent* rawEvent = rawEvents; count != 0; rawEvent++) {
   
    
    
    	 ...代码省略...
    	 //C++ Lambda 表达式,遍历与输入事件对应的设备ID关联的所有映射器,并调用每个映射器的process方法处理事件。
         for_each_mapper_in_subdevice(rawEvent->deviceId, [rawEvent](InputMapper& mapper) {
   
    
    
         	 //调用InputMapper的process方法
             mapper.process(rawEvent);
         });
        ...代码省略...
        --count;
    }
}

>frameworks/native/services/inputflinger/reader/include/InputDevice.h
inline void for_each_mapper_in_subdevice(int32_t eventHubDevice,
                                         std::function<void(InputMapper&)> f) {
   
    
    
    auto deviceIt = mDevices.find(eventHubDevice);//获取设备对象
    if (deviceIt != mDevices.end()) {
   
    
    
        auto& devicePair = deviceIt->second;
        auto& mappers = devicePair.second;
        for (auto& mapperPtr : mappers) {
   
    
    //获取设备对象的InputMapper集合,循环执行其方法,其实就是process方法
            f(*mapperPtr);
        }
    }
}
}

在注释1处通过deviceId获取输入设备在mDevices中实例对象,然后调用InputDevice实例对象的process方法,process方法会遍历所有输入事件,获取每个输入事件对应的设备ID关联的所有InputMapper映射器,并调用这些映射器的process方法处理事件。那么这些映射器是在什么地方被初始化的呢?

1.2.2 InputReader的addDeviceLocked方法

重新回到前面InputReader的processEventsLocked方法中,当一个输入事件类型为设备事件类型,且该设备事件类型为设备新增类型的时候,会调用addDeviceLocked方法来处理。

>frameworks/>native/services/inputflinger/reader/InputReader.cpp
void InputReader::addDeviceLocked(nsecs_t when, int32_t eventHubId) {
   
    
    
    if (mDevices.find(eventHubId) != mDevices.end()) {
   
    
    
        ALOGW("Ignoring spurious device added event for eventHubId %d.", eventHubId);
        return;
    }
    InputDeviceIdentifier identifier = mEventHub->getDeviceIdentifier(eventHubId);
    //注释1,调用createDeviceLocked方法创建InputDevice对象
    std::shared_ptr<InputDevice> device = createDeviceLocked(eventHubId, identifier);
    ...代码省略...
    //注释2,将新创建的device对象添加到事件节点设备对象集合中
    mDevices.emplace(eventHubId, device);
	...代码省略...
}

std::shared_ptr<InputDevice> InputReader::createDeviceLocked(
        int32_t eventHubId, const InputDeviceIdentifier& identifier) {
   
    
    
    auto deviceIt = std::find_if(mDevices.begin(), mDevices.end(), [identifier](auto& devicePair) {
   
    
    
        const InputDeviceIdentifier identifier2 =
                devicePair.second->getDeviceInfo().getIdentifier();
        return isSubDevice(identifier, identifier2);
    });

    std::shared_ptr<InputDevice> device;
    if (deviceIt != mDevices.end()) {
   
    
    
        device = deviceIt->second;
    } else {
   
    
    
        int32_t deviceId = (eventHubId < END_RESERVED_ID) ? eventHubId : nextInputDeviceIdLocked();
        //创建输入设备对象
        device = std::make_shared<InputDevice>(&mContext, deviceId, bumpGenerationLocked(),
                                               identifier);
    }
    //注释3,调用InputDevice的addEventHubDevice方法,将输入事件添加到输入设备对象中
    device->addEventHubDevice(eventHubId);
    return device;
}

在注释1处调用createDeviceLocked方法创建InputDevice对象。在注释2处将新创建的device对象添加到事件节点设备对象集合中。在注释3处,也就是createDeviceLocked方法中,调用InputDevice的addEventHubDevice方法,将输入事件添加到输入设备对象中。

1.3 InputDevice的addEventHubDevice方法

>frameworks/native/services/inputflinger/reader/include/InputDevice.h
class InputDevice {
   
    
    
private:
    using MapperVector = std::vector<std::unique_ptr<InputMapper>>;
    using DevicePair = std::pair<std::unique_ptr<InputDeviceContext>, MapperVector>;
    哈希映射表,里面存放了和eventHubId 关联的设备上下文和映射器列表
    std::unordered_map<int32_t, DevicePair> mDevices;
}
>frameworks/native/services/inputflinger/reader/InputDevice.cpp
void InputDevice::addEventHubDevice(int32_t eventHubId, bool populateMappers) {
   
    
    
    //注释1,检查是否已存在指定的设备
    if (mDevices.find(eventHubId) != mDevices.end()) {
   
    
    
        return;
    }
    //创建新的设备上下文
    std::unique_ptr<InputDeviceContext> contextPtr(new InputDeviceContext(*this, eventHubId));
    //获取设备类别
    Flags<InputDeviceClass> cla