当前位置: 首页 > article >正文

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> classes = contextPtr->getDeviceClasses();
    //创建输入事件映射器列表
    std::vector<std::unique_ptr<InputMapper>> mappers;

    if (!populateMappers) {
        mDevices.insert({eventHubId, std::make_pair(std::move(contextPtr), std::move(mappers))});
        return;
    }
    //注释2,根据设备类别创建相关的输入映射器
    //开关设备
    if (classes.test(InputDeviceClass::SWITCH)) {
        mappers.push_back(std::make_unique<SwitchInputMapper>(*contextPtr));
    }

    //旋转编码器设备
    if (classes.test(InputDeviceClass::ROTARY_ENCODER)) {
        mappers.push_back(std::make_unique<RotaryEncoderInputMapper>(*contextPtr));
    }

    //振动设备
    if (classes.test(InputDeviceClass::VIBRATOR)) {
        mappers.push_back(std::make_unique<VibratorInputMapper>(*contextPtr));
    }

    //电池或光源设备
    if (classes.test(InputDeviceClass::BATTERY) || classes.test(InputDeviceClass::LIGHT)) {
        mController = std::make_unique<PeripheralController>(*contextPtr);
    }

    //键盘和游戏控制器
    uint32_t keyboardSource = 0;
    int32_t keyboardType = AINPUT_KEYBOARD_TYPE_NON_ALPHABETIC;
    if (classes.test(InputDeviceClass::KEYBOARD)) {
        keyboardSource |= AINPUT_SOURCE_KEYBOARD;
    }
    if (classes.test(InputDeviceClass::ALPHAKEY)) {
        keyboardType = AINPUT_KEYBOARD_TYPE_ALPHABETIC;
    }
    if (classes.test(InputDeviceClass::DPAD)) {
        keyboardSource |= AINPUT_SOURCE_DPAD;
    }
    if (classes.test(InputDeviceClass::GAMEPAD)) {
        keyboardSource |= AINPUT_SOURCE_GAMEPAD;
    }

    if (keyboardSource != 0) {
        mappers.push_back(std::make_unique<KeyboardInputMapper>(*contextPtr, keyboardSource, keyboardType));
    }

    //光标设备
    if (classes.test(InputDeviceClass::CURSOR)) {
        mappers.push_back(std::make_unique<CursorInputMapper>(*contextPtr));
    }

    //触摸屏和触摸板设备
    if (classes.test(InputDeviceClass::TOUCH_MT)) {
        mappers.push_back(std::make_unique<MultiTouchInputMapper>(*contextPtr));
    } else if (classes.test(InputDeviceClass::TOUCH)) {
        mappers.push_back(std::make_unique<SingleTouchInputMapper>(*contextPtr));
    }

    //操纵杆设备
    if (classes.test(InputDeviceClass::JOYSTICK)) {
        mappers.push_back(std::make_unique<JoystickInputMapper>(*contextPtr));
    }

    //运动传感器设备
    if (classes.test(InputDeviceClass::SENSOR)) {
        mappers.push_back(std::make_unique<SensorInputMapper>(*contextPtr));
    }

    //外部手写笔设备
    if (classes.test(InputDeviceClass::EXTERNAL_STYLUS)) {
        mappers.push_back(std::make_unique<ExternalStylusInputMapper>(*contextPtr));
    }

    //注释3,将设备上下文和事件映射器插入到哈希映射表中
    mDevices.insert({eventHubId, std::make_pair(std::move(contextPtr), std::move(mappers))});
    //更新设备生成代号
    bumpGeneration();
}

在注释1处检查是否已存在指定的设备,如果存在直接返回,如果设备不存在,则创建新的设备上下文和相关的事件映射器列表。
在注释2处会根据设备类别创建相关的输入映射器,比如开关设备(SwitchInputMapper)、旋转编码器设备(RotaryEncoderInputMapper)、振动设备(VibratorInputMapper)、电池或光源设备(PeripheralController)、键盘设备(KeyboardInputMapper)、光标设备(CursorInputMapper)、触摸屏(MultiTouchInputMapper)和触摸板设备(SingleTouchInputMapper)、操纵杆设备(JoystickInputMapper)、运动传感器设备(SensorInputMapper)、外部手写笔设备(ExternalStylusInputMapper)。在注释3处将前面创建的设备上下文和事件映射器添加到哈希映射表mDevices中,方便后续查找,最后调用bumpGeneration方法更新设备生成代号。

1.4 InputMapper处理输入事件

重新回到前面InputReader的processEventsLocked方法中,当一个事件类型为原始输入事件类型的时候,会调用InputReader的processEventsForDeviceLocked方法,然后调用InputDevice的process方法,该方法会遍历自己所有的事件映射器,将原始输入事件交给InputMapper的process方法来出来,至于到底是那个InputMapper来处理,InputReader并不关心。

1.4.1 KeyboardInputMapper的process方法

这里我们结合处理键盘输入事件的KeyboardInputMapper这个映射器的process方法来作进一步分析。

>frameworks/native/services/inputflinger/reader/mapper/KeyboardInputMapper.cpp
//处理了键盘输入事件
void KeyboardInputMapper::process(const RawEvent* rawEvent) {
    switch (rawEvent->type) {
        case EV_KEY: {
            int32_t scanCode = rawEvent->code;
            int32_t usageCode = mCurrentHidUsage;
            mCurrentHidUsage = 0;
            if (isKeyboardOrGamepadKey(scanCode)) {
                //注释1,处理按键事件
                processKey(rawEvent->when, rawEvent->readTime, rawEvent->value != 0, scanCode,
                           usageCode);
            }
            break;
        }
        ...代码省略...
    }
}

void KeyboardInputMapper::processKey(nsecs_t when, nsecs_t readTime, bool down, int32_t scanCode,
                                     int32_t usageCode) {
	...代码省略...
    //注释2,将原始事件封装成一个新的NotifyKeyArgs对象
    NotifyKeyArgs args(getContext()->getNextId(), when, readTime, getDeviceId(), mSource,
                       getDisplayId(), policyFlags,
                       down ? AKEY_EVENT_ACTION_DOWN : AKEY_EVENT_ACTION_UP,
                       AKEY_EVENT_FLAG_FROM_SYSTEM, keyCode, scanCode, keyMetaState, downTime);
    //注释3,调用监听者的notifyKey方法,这里其实就是InputDispatcher对象
    getListener()->notifyKey(&args);
}

在注释1处调用processKey方法处理按键事件。在注释2处,也就是processKey方法内,将原始事件封装为一个新的NotifyKeyArgs对象。在注释3处,先是调用getListener方法获取监听者,然后调用监听者的notifyKey方法。这里获取的监听者最早是在InputReader的构造方法中初始化的。

1.4.2 InputReader初始化监听者

InputReader::InputReader(std::shared_ptr<EventHubInterface> eventHub,
                         const sp<InputReaderPolicyInterface>& policy,
                         const sp<InputListenerInterface>& listener)
      : mContext(this),
        mEventHub(eventHub),
        mPolicy(policy),
        mGlobalMetaState(0),
        mLedMetaState(AMETA_NUM_LOCK_ON),
        mGeneration(1),
        mNextInputDeviceId(END_RESERVED_ID),
        mDisableVirtualKeysTimeout(LLONG_MIN),
        mNextTimeout(LLONG_MAX),
        mConfigurationChangesToRefresh(0) {
    mQueuedListener = new QueuedInputListener(listener);//初始化监听者
    { // acquire lock
        std::scoped_lock _l(mLock);
        refreshConfigurationLocked(0);
        updateGlobalMetaStateLocked();
    } // release lock
}

InputListenerInterface* InputReader::ContextImpl::getListener() {
    return mReader->mQueuedListener.get();
}

>frameworks/native/services/inputflinger/include/InputListener.h
class QueuedInputListener : public InputListenerInterface {
private:
    sp<InputListenerInterface> mInnerListener;//监听者
    std::vector<NotifyArgs*> mArgsQueue;
};
>frameworks/native/services/inputflinger/InputListener.cpp
QueuedInputListener::QueuedInputListener(const sp<InputListenerInterface>& innerListener) :
        mInnerListener(innerListener) {
}

而InputReader最早是在InputManager的构造方法中被创建的。

>frameworks/native/services/inputflinger/InputManager.cpp
InputManager::InputManager(
        const sp<InputReaderPolicyInterface>& readerPolicy,
        const sp<InputDispatcherPolicyInterface>& dispatcherPolicy) {
    //创建inputDispatcher对象
    mDispatcher = createInputDispatcher(dispatcherPolicy);
    mClassifier = new InputClassifier(mDispatcher);
    //注释1,创建InputReader对象,其内部持有mDispatcher的引用
    mReader = createInputReader(readerPolicy, mClassifier);
}

>frameworks/native/services/inputflinger/reader/InputReaderFactory.cpp
sp<InputReaderInterface> createInputReader(const sp<InputReaderPolicyInterface>& policy,
                                           const sp<InputListenerInterface>& listener) {
    //创建InputReader对象
    return new InputReader(std::make_unique<EventHub>(), policy, listener);
}

在注释1处调用createInputReader方法,这里传入的第二个参数就是InputDispatcher,其内部会调用InputReader的构造方法。

1.4.3 KeyboardInputMapper的loopOnce方法

重新回到KeyboardInputMapper的processKey方法中。

>frameworks/native/services/inputflinger/reader/mapper/KeyboardInputMapper.cpp
//处理了键盘输入事件
void KeyboardInputMapper::processKey(nsecs_t when, nsecs_t readTime, bool down, int32_t scanCode,
                                     int32_t usageCode) {
	...代码省略...
    NotifyKeyArgs args(getContext()->getNextId(), when, readTime, getDeviceId(), mSource,
                       getDisplayId(), policyFlags,
                       down ? AKEY_EVENT_ACTION_DOWN : AKEY_EVENT_ACTION_UP,
                       AKEY_EVENT_FLAG_FROM_SYSTEM, keyCode, scanCode, keyMetaState, downTime);
    //调用监听者的notifyKey方法
    getListener()->notifyKey(&args);
}

该方法的最后会调用监听者的notifyKey方法。

>frameworks/native/services/inputflinger/InputListener.cpp
void QueuedInputListener::notifyKey(const NotifyKeyArgs* args) {
    traceEvent(__func__, args->id);
    //将NotifyKeyArgs对象存储到mArgsQueue队列中
    mArgsQueue.push_back(new NotifyKeyArgs(*args));
}

void QueuedInputListener::flush() {
   	...对事件进行处理...
}

可以发现QueuedInputListener的notifyKey方法只是将NotifyKeyArgs事件对象存储到mArgsQueue队列中,并没有真正对事件进行处理,真正对事件进行处理是在flush方法中,而QueuedInputListener的flush方法是在InputReader的loopOnce方法中被调用的。关于loopOnce这个方法的具体分析请参考Android 12系统源码_输入系统(二)InputManagerService服务这篇文章.

>frameworks/>native/services/inputflinger/reader/InputReader.cpp
void InputReader::loopOnce() {
  	...代码省略...
    mQueuedListener->flush();//刷新或处理排队的监听器事件。
}
void QueuedInputListener::flush() {
    size_t count = mArgsQueue.size();
    for (size_t i = 0; i < count; i++) {
        NotifyArgs* args = mArgsQueue[i];
        args->notify(mInnerListener);
        delete args;
    }
    mArgsQueue.clear();
}

QueuedInputListener的flush方法就是循环调用列表中的事件,并依次执行NotifyArgs的notify方法,传入的参数mInnerListener为初始化时的InputDispatcher对象。

1.4.4 NotifyArgs的notify方法

>frameworks/native/services/inputflinger/include/InputListener.h
struct NotifyArgs {
    virtual void notify(const sp<InputListenerInterface>& listener) const = 0;
};

notify方法是一个纯虚函数,由其子类实现。KeyboardInputMapper事件映射器对应的子类就是NotifyKeyArgs对象。

>struct NotifyKeyArgs : public NotifyArgs {
    virtual void notify(const sp<InputListenerInterface>& listener) const;
}

>frameworks/native/services/inputflinger/InputListener.cpp
NotifyKeyArgs::NotifyKeyArgs(const NotifyKeyArgs& other)
      : NotifyArgs(other.id, other.eventTime),
        deviceId(other.deviceId),
        source(other.source),
        displayId(other.displayId),
        policyFlags(other.policyFlags),
        action(other.action),
        flags(other.flags),
        keyCode(other.keyCode),
        scanCode(other.scanCode),
        metaState(other.metaState),
        downTime(other.downTime),
        readTime(other.readTime) {}
        
void NotifyKeyArgs::notify(const sp<InputListenerInterface>& listener) const {
    listener->notifyKey(this);//注释1
}

在注释1处调用listener的notifyKey方法,这里的listener就是InputDispatcher的对象。

1.5 InputDispatcher的notifyKey方法

>frameworks/native/services/inputflinger/dispatcher/InputDispatcher.h
class InputDispatcher : public android::InputDispatcherInterface, public gui::WindowInfosListener {
private:
	//这是一个双端队列,用于存储输入事件条目(EventEntry)
	//std::shared_ptr 表示使用智能指针来管理事件条目的生命周期。
	//GUARDED_BY(mLock)表明 mInboundQueue 由 mLock 进行保护,确保在多线程环境中对队列的访问是安全的。
    std::deque<std::shared_ptr<EventEntry>> mInboundQueue GUARDED_BY(mLock);
}
>frameworks/native/services/inputflinger/dispatcher/InputDispatcher.cpp
void InputDispatcher::notifyKey(const NotifyKeyArgs* args) {
	...代码省略...
    bool needWake;
    { // acquire lock
        mLock.lock();
		...代码省略...
        //注释1
        std::unique_ptr<KeyEntry> newEntry =
                std::make_unique<KeyEntry>(args->id, args->eventTime, args->deviceId, args->source,
                                           args->displayId, policyFlags, args->action, flags,
                                           keyCode, args->scanCode, metaState, repeatCount,
                                           args->downTime);
        //注释2
        needWake = enqueueInboundEventLocked(std::move(newEntry));
        mLock.unlock();
    } // release lock

    if (needWake) {
        //注释3
        mLooper->wake();
    }
}

bool InputDispatcher::enqueueInboundEventLocked(EventEntry* entry) {
    bool needWake = mInboundQueue.empty();
    //将newEntry对象压入mInboundQueue中
    mInboundQueue.push_back(std::move(newEntry));
   ...代码省略...
}

由于进入了InputDispatcher的“势力范围”,在注释1处会将NotifyKeyArgs事件重新封装为KeyEntry对象。在注释2处调用enqueueInboundEventLocked方法,该方法内部会将KeyEntry对象压入mInboundQueue中。在注释3处唤醒InputDispatche对应的线程。

1.6 输入事件的加工流程小结

1.SystemServer创建并启动InputManagerService
2.InputManagerService在native层创建一个NativeInputManager对象
3.NativeInputManager内部创建一个InputManager对象
4.InputManager的start方法会启动InputReader线程和InputDispatcher线程
5.在InputReader线程中调用EventHub的getEvents获取设备节点中的输入事件
6.并将输入事件封装为NotifyKeyArgs对象放入队列中
7.之后再调用flush,依次将事件传递给InputDispatcher
8.InputDispatcher在收到事件后,会重新封装为一个KeyEntry对象,并压力压入mInboundQueue列表中
9.最后唤醒InputDispatcherThread线程

二、输入事件的分发

我们在Android 12系统源码_输入系统(二)InputManagerService服务中有具体分析过InputDispatcher的start方法。

>frameworks/native/services/inputflinger/dispatcher/InputDispatcher.cpp
status_t InputDispatcher::start() {
    if (mThread) {
        return ALREADY_EXISTS;
    }
    //注释1,创建InputThread对象
    mThread = std::make_unique<InputThread>(
            "InputDispatcher", [this]() { dispatchOnce(); }, [this]() { mLooper->wake(); });
    return OK;
}

start方法会创建InputThread对象,该对象内部会启动名为InputDispatcher的线程,该线程会循环调用dispatchOnce方法。

2.1 InputDispatcher的dispatchOnce方法

>frameworks/native/services/inputflinger/dispatcher/InputDispatcher.cpp
void InputDispatcher::dispatchOnce() {
    nsecs_t nextWakeupTime = LONG_LONG_MAX;
    { // acquire lock
        std::scoped_lock _l(mLock);
        mDispatcherIsAlive.notify_all();

        //注释1,检测缓存队列中是否没有等待处理的指令
        if (!haveCommandsLocked()) {
            //调用dispatchOnceInnerLocked方法
            dispatchOnceInnerLocked(&nextWakeupTime);
        }
        //注释2,执行指令
        if (runCommandsLockedInterruptible()) {
              nextWakeupTime = LONG_LONG_MIN;
        }
        //检查ANR
        const nsecs_t nextAnrCheck = processAnrsLocked();
        nextWakeupTime = std::min(nextWakeupTime, nextAnrCheck);
        //处理空闲状态
        if (nextWakeupTime == LONG_LONG_MAX) {
            mDispatcherEnteredIdle.notify_all();
        }
    } // release lock

    //计算InputDisPatcherThread需要休眠的最长时间
    nsecs_t currentTime = now();
    int timeoutMillis = toMillisecondTimeoutDelay(currentTime, nextWakeupTime);
    //让mLooper线程休眠,timeoutMillis是休眠的最长时间
    mLooper->pollOnce(timeoutMillis);
}

在注释1处判断如果缓存队列中没有等待处理的指令,则会调用dispatchOnceInnerLocked方法来处理输入事件。如果当前有等待处理的指令,则在注释2处优先处理该指令,并将线程休眠时间nextWakeupTime设置为LONG_LONG_MIN,这样线程在执行完指令之后可以立刻被唤醒去处理输入事件。从这里可以看出dispatchOnce主要是做了两个功能:1.执行指令 2.处理输入事件,且指令执行优先级高于输入事件处理。例如对waitQueue中的事件进行出栈就属于指令的一种,这个后面我们还会讲到。

2.2 InputDispatcher的dispatchOnceInnerLocked方法

>frameworks/native/services/inputflinger/dispatcher/InputDispatcher.cpp
void InputDispatcher::dispatchOnceInnerLocked(nsecs_t* nextWakeupTime) {
    nsecs_t currentTime = now();
    if (!mDispatchEnabled) {
        //重置按键重复计数器
        resetKeyRepeatLocked();
    }
    //注释1,如果InputDispatcher被冻结,则不进行派发操作直接返回
    if (mDispatchFrozen) {
        if (DEBUG_FOCUS) {
            ALOGD("Dispatch frozen.  Waiting some more.");
        }
        return;
    }
    //注释2,如果isAppSwitchDue为true,则说明没有及时响应Home键操作
    bool isAppSwitchDue = mAppSwitchDueTime <= currentTime;
    if (mAppSwitchDueTime < *nextWakeupTime) {
        *nextWakeupTime = mAppSwitchDueTime;
    }

    if (!mPendingEvent) {
        //如果mInboundQueue为空,并且没有待分发的事件,直接返回
        if (mInboundQueue.empty()) {
			...代码省略...
            if (!mPendingEvent) {
                return;
            }
        } else {
            //注释3,将输入事件队列mInboundQueue最前端条目取出赋值给mPendingEvent
            mPendingEvent = mInboundQueue.front();
            mInboundQueue.pop_front();
            traceInboundQueueLengthLocked();
        }

        // Poke user activity for this event.
        if (mPendingEvent->policyFlags & POLICY_FLAG_PASS_TO_USER) {
            pokeUserActivityLocked(*mPendingEvent);
        }
    }
    
    ALOG_ASSERT(mPendingEvent != nullptr);
    bool done = false;
    //事件丢失的原因,默认为不丢失
    DropReason dropReason = DropReason::NOT_DROPPED;
    if (!(mPendingEvent->policyFlags & POLICY_FLAG_PASS_TO_USER)) {
        dropReason = DropReason::POLICY;
    } else if (!mDispatchEnabled) {
        dropReason = DropReason::DISABLED;
    }

    if (mNextUnblockedEvent == mPendingEvent) {
        mNextUnblockedEvent = nullptr;
    }
    //注释4,判断输入事件的类型
    switch (mPendingEvent->type) {
		...代码省略...    
        case EventEntry::Type::KEY: {//按键事件
            std::shared_ptr<KeyEntry> keyEntry = std::static_pointer_cast<KeyEntry>(mPendingEvent);
            if (isAppSwitchDue) {
                if (isAppSwitchKeyEvent(*keyEntry)) {
                    resetPendingAppSwitchLocked(true);
                    isAppSwitchDue = false;
                } else if (dropReason == DropReason::NOT_DROPPED) {
                    dropReason = DropReason::APP_SWITCH;
                }
            }
            //事件过期
            if (dropReason == DropReason::NOT_DROPPED && isStaleEvent(currentTime, *keyEntry)) {
                dropReason = DropReason::STALE;
            }
            //阻碍其他窗口获取事件
            if (dropReason == DropReason::NOT_DROPPED && mNextUnblockedEvent) {
                dropReason = DropReason::BLOCKED;
            }
            //注释5,调用dispatchKeyLocked方法分发按键事件
            done = dispatchKeyLocked(currentTime, keyEntry, &dropReason, nextWakeupTime);
            break;
        }
        case EventEntry::Type::MOTION: {//触摸事件
            std::shared_ptr<MotionEntry> motionEntry =
                    std::static_pointer_cast<MotionEntry>(mPendingEvent);
            //如果没有及时响应窗口切换操作
            if (dropReason == DropReason::NOT_DROPPED && isAppSwitchDue) {
                dropReason = DropReason::APP_SWITCH;
            }
            //事件过期
            if (dropReason == DropReason::NOT_DROPPED && isStaleEvent(currentTime, *motionEntry)) {
                dropReason = DropReason::STALE;
            }
            //阻碍其他窗口获取事件
            if (dropReason == DropReason::NOT_DROPPED && mNextUnblockedEvent) {
                dropReason = DropReason::BLOCKED;
            }
            //调用dispatchMotionLocked方法分发触摸事件
            done = dispatchMotionLocked(currentTime, motionEntry, &dropReason, nextWakeupTime);
            break;
        }
        case EventEntry::Type::SENSOR: {
            std::shared_ptr<SensorEntry> sensorEntry =
                    std::static_pointer_cast<SensorEntry>(mPendingEvent);
            if (dropReason == DropReason::NOT_DROPPED && isAppSwitchDue) {
                dropReason = DropReason::APP_SWITCH;
            }
            nsecs_t bootTime = systemTime(SYSTEM_TIME_BOOTTIME);
            if (dropReason == DropReason::NOT_DROPPED && isStaleEvent(bootTime, *sensorEntry)) {
                dropReason = DropReason::STALE;
            }
            dispatchSensorLocked(currentTime, sensorEntry, &dropReason, nextWakeupTime);
            done = true;
            break;
        }
    }

    if (done) {
        if (dropReason != DropReason::NOT_DROPPED) {
            dropInboundEventLocked(*mPendingEvent, dropReason);
        }
        mLastDropReason = dropReason;
        //注释6,释放本次处理完毕的分发事件对象
        releasePendingEventLocked();
        //注释7,使InputDispatcher能够立刻进行下一次事件的分发
        *nextWakeupTime = LONG_LONG_MIN; 
    }
}

在注释1处,判断如果当前InputDispatcher被冻结,则不进行分发操作,InputDispatcher有三种状态:正常、冻结、禁用;可以通过InputDispatcher的setInputDispatchMode方法进行设置。在注释2处,mAppSwitchDueTime代表了App最近发生窗口切换操作时(比如按Home键,挂断电话),该操作事件最迟的分发时间,如果mAppSwitchDueTime小于或等于当前系统时间,说明没有及时响应窗口切换的操作,则isAppSwitchDue的值为true,如果mAppSwitchDueTime小于nextWakeupTime,这样当InputDispatcher处理完分发事件后,会立刻被唤醒执行窗口切换操作。在注释3处会将输入事件队列mInboundQueue最前端条目取出赋值给mPendingEvent。然后在注释4处判断输入事件的类型。如果为按键事件,则在注释5处调用dispatchKeyLocked方法开始分发按键事件。在注释6处会释放本次处理完毕的分发事件对象。然后将休眠时间设置为最短休眠时间,以便InputDispatcher能立刻被唤醒以便进行下一次事件的分发。

2.3 InputDispatcher的dispatchKeyLocked方法

>frameworks/native/services/inputflinger/dispatcher/InputDispatcher.cpp
bool InputDispatcher::dispatchKeyLocked(nsecs_t currentTime, std::shared_ptr<KeyEntry> entry,
                                        DropReason* dropReason, nsecs_t* nextWakeupTime) {
	...代码省略...
    //如果事件是需要丢弃的,则返回true,不再为该事件寻找合适的窗口
    if (*dropReason != DropReason::NOT_DROPPED) {
        setInjectionResult(*entry,
                           *dropReason == DropReason::POLICY ? InputEventInjectionResult::SUCCEEDED
                                                             : InputEventInjectionResult::FAILED);
        mReporter->reportDroppedKey(entry->id);
        return true;
    }

    //目标窗口列表
    std::vector<InputTarget> inputTargets;
    //注释1,调用findFocusedWindowTargetsLocked查找焦点窗口
    InputEventInjectionResult injectionResult =
            findFocusedWindowTargetsLocked(currentTime, *entry, inputTargets, nextWakeupTime);
    //输入事件被挂起,说明找到了窗口但是窗口无响应
    if (injectionResult == InputEventInjectionResult::PENDING) {
        return false;
    }

    setInjectionResult(*entry, injectionResult);
    //输入事件没有分发成功,说明没有找到合适的窗口
    if (injectionResult != InputEventInjectionResult::SUCCEEDED) {
        return true;
    }

    //将分发的目标添加到inputTargets列表中
    addGlobalMonitoringTargetsLocked(inputTargets, getTargetDisplayId(*entry));

    //注释2,调用dispatchEventLocked方法
    dispatchEventLocked(currentTime, entry, inputTargets);
    return true;
}

在注释1处会调用findFocusedWindowTargetsLocked查找当前的焦点窗口并将其存储到inputTargets中。然后在注释2处,会调用dispatchEventLocked方法将输入事件分发给inputTargets列表中的目标窗口。

2.4 InputDispatcher的dispatchEventLocked方法

>frameworks/native/services/inputflinger/dispatcher/InputDispatcher.h
class InputDispatcher : public android::InputDispatcherInterface, public gui::WindowInfosListener {
private:
    std::unordered_map<sp<IBinder>, sp<Connection>, StrongPointerHash<IBinder>> mConnectionsByToken
            GUARDED_BY(mLock);
}
>frameworks/native/services/inputflinger/dispatcher/InputDispatcher.cpp
void InputDispatcher::dispatchEventLocked(nsecs_t currentTime,
                                          std::shared_ptr<EventEntry> eventEntry,
                                          const std::vector<InputTarget>& inputTargets) {
	...代码省略...
    pokeUserActivityLocked(*eventEntry);
    //遍历inputTargets列表
    for (const InputTarget& inputTarget : inputTargets) {
        //注释1,调用getConnectionLocked方法获取当前inputTarget对应的connection
        sp<Connection> connection = getConnectionLocked(inputTarget.inputChannel->getConnectionToken());
        if (connection != nullptr) {
            //注释2,调用prepareDispatchCycleLocked方法开始事件分发循环
            prepareDispatchCycleLocked(currentTime, connection, eventEntry, inputTarget);
        } else {
            if (DEBUG_FOCUS) {
                ALOGD("Dropping event delivery to target with channel '%s' because it "
                      "is no longer registered with the input dispatcher.",
                      inputTarget.inputChannel->getName().c_str());
            }
        }
    }
}

sp<Connection> InputDispatcher::getConnectionLocked(const sp<IBinder>& inputConnectionToken) const {
    if (inputConnectionToken == nullptr) {
        return nullptr;
    }
    //遍历mConnectionsByToken
    for (const auto& [token, connection] : mConnectionsByToken) {
    	//如果token相等,则返回该对象
        if (token == inputConnectionToken) {
            return connection;
        }
    }
    return nullptr;
}

在注释1处调用getConnectionLocked方法,传入当前inputTarget对应的连接令牌,该方法内部会遍历当前存在的所有窗口连接,返回和当前inputTarget令牌相等的窗口连接对象connection 。然后在注释2处调用prepareDispatchCycleLocked方法开始事件分发循环。

2.5 输入事件的加工和分发流程小结

1.InputReader将设备节点中的输入事件进行加工并发送给InputDispatcher
2.InputDispatcher在收到事件后,会重新封装为一个KeyEntry对象,并压入mInboundQueue列表中,唤醒InputDispatcher线程
3.InputDispatcher线程会循环调用dispatchOnce方法,将存放在mInboundQueue列表中的输入事件依次取出,并判断根据输入事件的具体类型调用对应的事件分发方法
4.如果是按键事件,则会调用dispatchKeyLocked方法;如果是触摸事件,则会调用dispatchMotionLocked方法
5.在调用特定dispatch*Locked方法进行特定事件分发的过程中,都会先调用findFocusedWindowTargetsLocked方法查找当前系统的焦点窗口,然后将输入事件分发给焦点目标窗口

三、系统窗口状态数据的传递

我们在Android 12系统源码_窗口管理(二)WindowManager对窗口的管理过程这篇文章有讲过,代表窗口视图的Window是在ViewRootImpl的setView方法中传入WMS的。

frameworks/base/core/java/android/view/ViewRootImpl.java

public final class ViewRootImpl implements ViewParent,
        View.AttachInfo.Callbacks, ThreadedRenderer.DrawCallbacks {
    
    final IWindowSession mWindowSession;
    final W mWindow;
    final View.AttachInfo mAttachInfo;

    public void setView(View view, WindowManager.LayoutParams attrs, View panelParentView,
            int userId) {
        synchronized (this) {
                 ...代码省略...
                InputChannel inputChannel = null;
                if ((mWindowAttributes.inputFeatures
                        & WindowManager.LayoutParams.INPUT_FEATURE_NO_INPUT_CHANNEL) == 0) {
                    inputChannel = new InputChannel();
                }
                ...代码省略...
                res = mWindowSession.addToDisplayAsUser(mWindow, mWindowAttributes,
                        getHostVisibility(), mDisplay.getDisplayId(), userId,
                        mInsetsController.getRequestedVisibilities(), inputChannel, mTempInsets,
                        mTempControls);
              ...代码省略...
    }
}
>frameworks/base/services/core/java/com/android/server/wm/Session.java
class Session extends IWindowSession.Stub implements IBinder.DeathRecipient {
    @Override
    public int addToDisplay(IWindow window, WindowManager.LayoutParams attrs,
            int viewVisibility, int displayId, InsetsVisibilities requestedVisibilities,
            InputChannel outInputChannel, InsetsState outInsetsState,
            InsetsSourceControl[] outActiveControls) {
        return mService.addWindow(this, window, attrs, viewVisibility, displayId,
                UserHandle.getUserId(mUid), requestedVisibilities, outInputChannel, outInsetsState,
                outActiveControls);
    }
}
>frameworks/base/services/core/java/com/android/server/wm/WindowManagerService.java
public class WindowManagerService extends IWindowManager.Stub
        implements Watchdog.Monitor, WindowManagerPolicy.WindowManagerFuncs {
        
    //窗口管理策略的接口类,用来定义一个窗口策略所要遵循的通用规范,具体实现类为PhoneWindowManager。
    final WindowManagerPolicy mPolicy;
    
    public int addWindow(Session session, IWindow client, LayoutParams attrs, int viewVisibility,
            int displayId, int requestUserId, InsetsVisibilities requestedVisibilities,
            InputChannel outInputChannel, InsetsState outInsetsState,
            InsetsSourceControl[] outActiveControls) {
		...代码省略...
        //创建窗口状态对象,该对象包含窗口所对应的所有信息,它就是要添加的窗口对象
        final WindowState win = new WindowState(this, session, client, token, parentWindow,
                appOp[0], attrs, viewVisibility, session.mUid, userId,
                session.mCanAddInternalSystemWindow);
		...代码省略...                
        //检验窗口是否可以被添加到系统中
        res = displayPolicy.validateAddingWindowLw(attrs, callingPid, callingUid);
        android.util.Log.d(TAG, "addWindow: res = "+res);
        if (res != ADD_OKAY) {
            return res;
        }
        final boolean openInputChannels = (outInputChannel != null
        && (attrs.inputFeatures & INPUT_FEATURE_NO_INPUT_CHANNEL) == 0);
        if (openInputChannels) {
            win.openInputChannel(outInputChannel);
        }
		...代码省略...
    }
}
>frameworks/base/services/core/java/com/android/server/wm/WindowState.java
class WindowState extends WindowContainer<WindowState> implements WindowManagerPolicy.WindowState,
        InsetsControlTarget, InputTarget {
        
    void openInputChannel(InputChannel outInputChannel) {
        if (mInputChannel != null) {
            throw new IllegalStateException("Window already has an input channel.");
        }
        String name = getName();
        mInputChannel = mWmService.mInputManager.createInputChannel(name);
        mInputChannelToken = mInputChannel.getToken();
        mInputWindowHandle.setToken(mInputChannelToken);
        mWmService.mInputToWindowMap.put(mInputChannelToken, this);
        if (outInputChannel != null) {
            mInputChannel.copyTo(outInputChannel);
        } else {
            // If the window died visible, we setup a fake input channel, so that taps
            // can still detected by input monitor channel, and we can relaunch the app.
            // Create fake event receiver that simply reports all events as handled.
            mDeadWindowEventReceiver = new DeadWindowEventReceiver(mInputChannel);
        }
    }
    
}
>frameworks/base/services/core/java/com/android/server/input/InputManagerService.java
public class InputManagerService extends IInputManager.Stub
        implements Watchdog.Monitor {
    
    private static native InputChannel nativeCreateInputChannel(long ptr, String name);
    
    public InputChannel createInputChannel(String name) {
        return nativeCreateInputChannel(mPtr, name);
    }
}
>frameworks/base/services/core/jni/com_android_server_input_InputManagerService.cpp
static jobject nativeCreateInputChannel(JNIEnv* env, jclass /* clazz */, jlong ptr,
                                        jstring nameObj) {
    //获取NativeInputManager 实例
    NativeInputManager* im = reinterpret_cast<NativeInputManager*>(ptr);
    //转换 Java 字符串
    ScopedUtfChars nameChars(env, nameObj);
    std::string name = nameChars.c_str();
    //注释1,创建Native层的InputChannel对象
    base::Result<std::unique_ptr<InputChannel>> inputChannel = im->createInputChannel(env, name);
    //如果创建 InputChannel 失败,生成错误消息并抛出一个 RuntimeException,返回 nullptr。
    if (!inputChannel.ok()) {
        std::string message = inputChannel.error().message();
        message += StringPrintf(" Status=%d", inputChannel.error().code());
        jniThrowRuntimeException(env, message.c_str());
        return nullptr;
    }
    //注释3,将Navite层的inputChannel对象转化为Java层的inputChannel对象
    jobject inputChannelObj = android_view_InputChannel_createJavaObject(env, std::move(*inputChannel));
    if (!inputChannelObj) {
        return nullptr;
    }
    //设置一个回调函数 handleInputChannelDisposed,以便在Java层InputChannel被垃圾回收时处理清理操作。
    android_view_InputChannel_setDisposeCallback(env, inputChannelObj, handleInputChannelDisposed, im);
    //返回Java层的InputChannel对象
    return inputChannelObj;
}

base::Result<std::unique_ptr<InputChannel>> NativeInputManager::createInputChannel(
        JNIEnv* /* env */, const std::string& name) {
    ATRACE_CALL();
    //注释2,调用InputDispatcher的createInputChannel方法
    return mInputManager->getDispatcher()->createInputChannel(name);
}

>frameworks/native/services/inputflinger/dispatcher/InputDispatcher.cpp
Result<std::unique_ptr<InputChannel>> InputDispatcher::createInputChannel(const std::string& name) {
#if DEBUG_CHANNEL_CREATION
    ALOGD("channel '%s' ~ createInputChannel", name.c_str());
#endif

    std::unique_ptr<InputChannel> serverChannel;
    std::unique_ptr<InputChannel> clientChannel;
    status_t result = InputChannel::openInputChannelPair(name, serverChannel, clientChannel);

    if (result) {
        return base::Error(result) << "Failed to open input channel pair with name " << name;
    }

    { // acquire lock
        std::scoped_lock _l(mLock);
        const sp<IBinder>& token = serverChannel->getConnectionToken();
        int fd = serverChannel->getFd();
        sp<Connection> connection =
                new Connection(std::move(serverChannel), false /*monitor*/, mIdGenerator);

        if (mConnectionsByToken.find(token) != mConnectionsByToken.end()) {
            ALOGE("Created a new connection, but the token %p is already known", token.get());
        }
        mConnectionsByToken.emplace(token, connection);

        std::function<int(int events)> callback = std::bind(&InputDispatcher::handleReceiveCallback,
                                                            this, std::placeholders::_1, token);

        mLooper->addFd(fd, 0, ALOOPER_EVENT_INPUT, new LooperEventCallback(callback), nullptr);
    } // release lock

    // Wake the looper because some connections have changed.
    mLooper->wake();
    return clientChannel;
}

http://www.kler.cn/news/326959.html

相关文章:

  • Spring RestTemplate 升级 WebClient 导致 OutOfMemoryError
  • SQL进阶技巧:如何利用if语句简化where或join中的条件 | if条件语句的优雅使用方法
  • QT界面制作
  • 粉丝们得以一窥索菲亚罗兰奢华的90岁生日庆祝仪式! 她已完成了所有的遗愿清单 !
  • 选择租用徐州存储服务器有什么作用?
  • 大数据-149 Apache Druid 基本介绍 技术特点 应用场景
  • 2024年7月大众点评广州美食店铺基础信息
  • 2024.9.24 作业
  • Stable Diffusion 蒙版:填充、原图、潜空间噪声(潜变量噪声)、潜空间数值零(潜变量数值零)
  • 我店生活系统小程序开发功能解析
  • uniapp框架中实现文件选择上传组件,可以选择图片、视频等任意文件并上传到当前绑定的服务空间
  • 修改 idea 的 Terminal 命令窗口使用 git-bash
  • 得物App荣获新奖项,科技创新助力高质量发展
  • 国内ChatGPT镜像网站整理汇总【OpenAI o1/GPT 4o】-2024/10月最新
  • 【数据结构与算法】算法和算法分析
  • nginx服务介绍
  • ros2 colcon build 构建后,install中的local_setup.bash 和setup.bash有什么区别
  • 企业数据可视化大屏的工具选择有哪些
  • UI设计师面试整理-设计趋势和行业理解
  • 互斥量mutex、锁、条件变量和信号量相关原语(函数)----很全
  • 从两个 Excel 表格中提取相关信息,并根据学生的 学号 和 姓名 将第一个表格中的成绩数据填充到第二个表格中(附Python代码)
  • 【LeetCode HOT 100】详细题解之链表篇
  • 【Kubernetes】常见面试题汇总(四十八)
  • MySQL实现跨服务器查询
  • Vscode超好看的渐变主题插件
  • Axure9破解
  • MySQL中的嵌套查询
  • Go实现RabbitMQ消息模式
  • 科研绘图系列:R语言堆积图(stacked barplot)
  • 数据驱动农业——农业中的大数据