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