InputReader process review

Brief description of event distribution mechanism

What is the entire process of event delivery?
Because View has a tree structure, events are distributed in an orderly manner based on this structure. Event distribution is when there are multiple objects that can handle the same request, concatenating these objects into a chain, and passing the request along this chain until an object handles it.
After the event is collected, it is first passed to the Activity, and then passed down in sequence:
Activity->PhoneWindow->DecorView->ViewGroup->...->View
. When a touch event is triggered, the event is first distributed to the dispatchTouchEvent() method of the Activity. , Activity will first distribute the event to Window for processing, and then Window will call superDispatchTouchEvent() method; then PhoneWindow will call DecorViewsuperDispatchTouchEvent() method. Finally, DecorView calls the dispatchTouchEvent() method of ViewGroup for event distribution. In this way, it is distributed step by step to the dispatchTouchEvent() method of the ViewGroup passed in by the user calling setContentView().
When the dispatchTouchEvent() method of ViewGroup allows the event to be distributed, the onInterceptTouchEvent() method will be called first to determine whether to intercept the event. If intercepted, mFirstTouchTarget will be null; if not intercepted, the corresponding sub-control will be found for event processing. In the end, dispatchTransformedTouchEvent() will be called regardless of whether the child control that handles it is found.
If no View consumes the event in the end, the event will be passed back in the opposite direction and eventually passed back to the Activity. If the Activity does not handle it in the end, this event will be abandoned.

overall process

status_t InputManager::start() {
    
    
    status_t result = mDispatcherThread->run("InputDispatcher", PRIORITY_URGENT_DISPLAY);
    //...
    result = mReaderThread->run("InputReader", PRIORITY_URGENT_DISPLAY);
    //...
    return OK;
}

InputManager starts an InputReaderThread and InputDispatcherThread to read and distribute input messages. After calling their run method, it will enter the threadLoop function (as long as the threadLoop function returns true, the function will be executed in a loop). Therefore, we directly analyze the threadLoop function of InputReaderThread and implement it as follows:

bool InputReaderThread::threadLoop() {
    
    
    mReader->loopOnce();
    return true;
}

loopOnce

void InputReader::loopOnce() {
    
    
    int32_t oldGeneration;
    int32_t timeoutMillis;
    bool inputDevicesChanged = false;
    Vector<InputDeviceInfo> inputDevices;
    //...
    //关键点1 通过EventHub获取事件列表
    size_t count = mEventHub->getEvents(timeoutMillis, mEventBuffer, EVENT_BUFFER_SIZE);
 
    {
    
     // acquire lock
        AutoMutex _l(mLock);
        mReaderIsAliveCondition.broadcast();
        if (count) {
    
    
            //关键点2 对事件进行 加工处理
            processEventsLocked(mEventBuffer, count);
        }
        //...
    } // release lock
 
    // Send out a message that the describes the changed input devices.
    if (inputDevicesChanged) {
    
    
        mPolicy->notifyInputDevicesChanged(inputDevices);
    }
    //关键点3 发布事件到InputDispatcher中
    mQueuedListener->flush();
}

Taking InputReader::loopOnce() as the starting point and multi-finger touch as an example
Insert image description here

  1. Get the event list from EventHub.
    Events are divided into two categories: raw input events read in device nodes, and input device availability change events (device events).
    The purpose of obtaining input events is to extract the input events from the driver and convert them into RawEvent events. At the same time, the input device is abstracted into a Device structure in EventHub and stored.
    EventHub is responsible for opening all devices in the /dev/input/ directory, then creating a Device for each device, and putting this Device into the array mDevice defined by EventHub. Then put the device under surveillance. Next, wait for the event to occur. Once an event occurs, read these devices from the device that generated the input_event event, convert these events into RawEvent types and put them into the event array provided by InputReader, and then return.
struct RawEvent {
    
    
    // Time when the event happened
    nsecs_t when;
    // Time when the event was read by EventHub. Only populated for input events.
    // For other events (device added/removed/etc), this value is undefined and should not be read.
    nsecs_t readTime;
    int32_t deviceId;//产生事件的设备Id,由EventHub自行分配,InputReader根据它从EventHub中获取此设备的详细信息
    int32_t type;//事件的类型 
    int32_t code;//事件代码
    int32_t value;//事件值
};
  1. Process events and data processing through processEventsLocked().
    Determine the type. If you have started touching, the type value will definitely be small. 于FIRST_SYNTHETIC_EVENTEnter processEventsForDeviceLocked()the method to start processing data. Otherwise, add, delete or configure the device. Here we take adding as an example addDeviceLocked(). Here we mainly create the InputDevice device and add various capabilities to the device according to the class. Supported Mapper. Finally added to the Vector container of mDevices.
    For device events, this function loads or removes the configuration information corresponding to the device based on the device's availability. For original input events, the results are stored in mQueuedListener after translation, encapsulation and processing.

  2. Publish events to InputDispatcher
    After all events are processed, call mQueuedListener.flush() to deliver all temporary input events to InputDispatcher at once.

Guess you like

Origin blog.csdn.net/yimelancholy/article/details/130469186