做宠物网站的工作室,idstore wordpress,建筑图纸怎样识图,wordpress在线代码编辑前言
上一篇文章我们具体分析了InputManagerService的构造方法和start方法#xff0c;知道IMS的start方法经过层层调用#xff0c;最终会触发Navite层InputDispatcher的start方法和InputReader的start方法。InputDispatcher的start方法会启动一个名为InputDispatcher的线程知道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_uniqueInputThread(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.cppvoid 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); // cant happenbreak;}}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_ptrInputDevice 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::functionvoid(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_ptrInputDevice device createDeviceLocked(eventHubId, identifier);...代码省略...//注释2将新创建的device对象添加到事件节点设备对象集合中mDevices.emplace(eventHubId, device);...代码省略...
}std::shared_ptrInputDevice 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_ptrInputDevice device;if (deviceIt ! mDevices.end()) {device deviceIt-second;} else {int32_t deviceId (eventHubId END_RESERVED_ID) ? eventHubId : nextInputDeviceIdLocked();//创建输入设备对象device std::make_sharedInputDevice(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::vectorstd::unique_ptrInputMapper;using DevicePair std::pairstd::unique_ptrInputDeviceContext, MapperVector;哈希映射表里面存放了和eventHubId 关联的设备上下文和映射器列表std::unordered_mapint32_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_ptrInputDeviceContext contextPtr(new InputDeviceContext(*this, eventHubId));//获取设备类别FlagsInputDeviceClass classes contextPtr-getDeviceClasses();//创建输入事件映射器列表std::vectorstd::unique_ptrInputMapper 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_uniqueSwitchInputMapper(*contextPtr));}//旋转编码器设备if (classes.test(InputDeviceClass::ROTARY_ENCODER)) {mappers.push_back(std::make_uniqueRotaryEncoderInputMapper(*contextPtr));}//振动设备if (classes.test(InputDeviceClass::VIBRATOR)) {mappers.push_back(std::make_uniqueVibratorInputMapper(*contextPtr));}//电池或光源设备if (classes.test(InputDeviceClass::BATTERY) || classes.test(InputDeviceClass::LIGHT)) {mController std::make_uniquePeripheralController(*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_uniqueKeyboardInputMapper(*contextPtr, keyboardSource, keyboardType));}//光标设备if (classes.test(InputDeviceClass::CURSOR)) {mappers.push_back(std::make_uniqueCursorInputMapper(*contextPtr));}//触摸屏和触摸板设备if (classes.test(InputDeviceClass::TOUCH_MT)) {mappers.push_back(std::make_uniqueMultiTouchInputMapper(*contextPtr));} else if (classes.test(InputDeviceClass::TOUCH)) {mappers.push_back(std::make_uniqueSingleTouchInputMapper(*contextPtr));}//操纵杆设备if (classes.test(InputDeviceClass::JOYSTICK)) {mappers.push_back(std::make_uniqueJoystickInputMapper(*contextPtr));}//运动传感器设备if (classes.test(InputDeviceClass::SENSOR)) {mappers.push_back(std::make_uniqueSensorInputMapper(*contextPtr));}//外部手写笔设备if (classes.test(InputDeviceClass::EXTERNAL_STYLUS)) {mappers.push_back(std::make_uniqueExternalStylusInputMapper(*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_ptrEventHubInterface eventHub,const spInputReaderPolicyInterface policy,const spInputListenerInterface 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 lockstd::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:spInputListenerInterface mInnerListener;//监听者std::vectorNotifyArgs* mArgsQueue;
};
frameworks/native/services/inputflinger/InputListener.cpp
QueuedInputListener::QueuedInputListener(const spInputListenerInterface innerListener) :mInnerListener(innerListener) {
}而InputReader最早是在InputManager的构造方法中被创建的。
frameworks/native/services/inputflinger/InputManager.cpp
InputManager::InputManager(const spInputReaderPolicyInterface readerPolicy,const spInputDispatcherPolicyInterface dispatcherPolicy) {//创建inputDispatcher对象mDispatcher createInputDispatcher(dispatcherPolicy);mClassifier new InputClassifier(mDispatcher);//注释1创建InputReader对象其内部持有mDispatcher的引用mReader createInputReader(readerPolicy, mClassifier);
}frameworks/native/services/inputflinger/reader/InputReaderFactory.cpp
spInputReaderInterface createInputReader(const spInputReaderPolicyInterface policy,const spInputListenerInterface listener) {//创建InputReader对象return new InputReader(std::make_uniqueEventHub(), 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 spInputListenerInterface listener) const 0;
};notify方法是一个纯虚函数由其子类实现。KeyboardInputMapper事件映射器对应的子类就是NotifyKeyArgs对象。
struct NotifyKeyArgs : public NotifyArgs {virtual void notify(const spInputListenerInterface 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 spInputListenerInterface 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::dequestd::shared_ptrEventEntry mInboundQueue GUARDED_BY(mLock);
}
frameworks/native/services/inputflinger/dispatcher/InputDispatcher.cpp
void InputDispatcher::notifyKey(const NotifyKeyArgs* args) {...代码省略...bool needWake;{ // acquire lockmLock.lock();...代码省略...//注释1std::unique_ptrKeyEntry newEntry std::make_uniqueKeyEntry(args-id, args-eventTime, args-deviceId, args-source,args-displayId, policyFlags, args-action, flags,keyCode, args-scanCode, metaState, repeatCount,args-downTime);//注释2needWake enqueueInboundEventLocked(std::move(newEntry));mLock.unlock();} // release lockif (needWake) {//注释3mLooper-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_uniqueInputThread(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 lockstd::scoped_lock _l(mLock);mDispatcherIsAlive.notify_all();//注释1检测缓存队列中是否没有等待处理的指令if (!haveCommandsLocked()) {//调用dispatchOnceInnerLocked方法dispatchOnceInnerLocked(nextWakeupTime);}//注释2执行指令if (runCommandsLockedInterruptible()) {nextWakeupTime LONG_LONG_MIN;}//检查ANRconst 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最前端条目取出赋值给mPendingEventmPendingEvent 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_ptrKeyEntry keyEntry std::static_pointer_castKeyEntry(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_ptrMotionEntry motionEntry std::static_pointer_castMotionEntry(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_ptrSensorEntry sensorEntry std::static_pointer_castSensorEntry(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_ptrKeyEntry 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::vectorInputTarget 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_mapspIBinder, spConnection, StrongPointerHashIBinder mConnectionsByTokenGUARDED_BY(mLock);
}
frameworks/native/services/inputflinger/dispatcher/InputDispatcher.cpp
void InputDispatcher::dispatchEventLocked(nsecs_t currentTime,std::shared_ptrEventEntry eventEntry,const std::vectorInputTarget inputTargets) {...代码省略...pokeUserActivityLocked(*eventEntry);//遍历inputTargets列表for (const InputTarget inputTarget : inputTargets) {//注释1调用getConnectionLocked方法获取当前inputTarget对应的connectionspConnection 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());}}}
}spConnection InputDispatcher::getConnectionLocked(const spIBinder inputConnectionToken) const {if (inputConnectionToken nullptr) {return nullptr;}//遍历mConnectionsByTokenfor (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 {Overridepublic 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.Stubimplements 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 WindowContainerWindowState 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.Stubimplements 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_castNativeInputManager*(ptr);//转换 Java 字符串ScopedUtfChars nameChars(env, nameObj);std::string name nameChars.c_str();//注释1创建Native层的InputChannel对象base::Resultstd::unique_ptrInputChannel 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::Resultstd::unique_ptrInputChannel 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
Resultstd::unique_ptrInputChannel InputDispatcher::createInputChannel(const std::string name) {
#if DEBUG_CHANNEL_CREATIONALOGD(channel %s ~ createInputChannel, name.c_str());
#endifstd::unique_ptrInputChannel serverChannel;std::unique_ptrInputChannel 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 lockstd::scoped_lock _l(mLock);const spIBinder token serverChannel-getConnectionToken();int fd serverChannel-getFd();spConnection 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::functionint(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;
}