本文基于Android 12。
一、InputManagerService启动
SystemServer初始化InputManagerService(),然后调用其start()方法。
InputManagerService()构造方法中和start()分别调用了两个native方法:
1.1NativeImpl() 初始化
InputManagerService(Injector injector) {mNative = injector.getNativeService(this);}NativeInputManagerService getNativeService(InputManagerService service) {return new NativeInputManagerService.NativeImpl(service, mContext, mLooper.getQueue());}
1.2 start() 启动
public void start() {mNative.start();}
其中mLooper是DisplayThread.get().getLooper(),DisplayThread是systemserver进程中的单例模式,只能被WindowManager,DisplayManager, InputManager使用。
二、NativeInputManager, InputManager
2.1 NativeInputManager
NativeInputManagerService.NativeImpl()方法初始化NativeInputManager对象,参数中还把InputManagerService和mLooper也一起传递过去了,NativeInputManager定义在jni代码中。
// com_android_server_input_InputManagerService.cppclass NativeInputManager : public virtual RefBase,public virtual InputReaderPolicyInterface,public virtual InputDispatcherPolicyInterface,public virtual PointerControllerPolicyInterface {}NativeInputManager::NativeInputManager(jobject contextObj,jobject serviceObj, const sp<Looper>& looper) :mLooper(looper), mInteractive(true) {JNIEnv* env = jniEnv();mServiceObj = env->NewGlobalRef(serviceObj);{AutoMutex _l(mLock);mLocked.systemUiLightsOut = false;mLocked.pointerSpeed = 0;mLocked.pointerAcceleration = android::os::IInputConstants::DEFAULT_POINTER_ACCELERATION;mLocked.pointerGesturesEnabled = true;mLocked.showTouches = false;mLocked.pointerDisplayId = ADISPLAY_ID_DEFAULT;}mInteractive = true;InputManager* im = new InputManager(this, this);mInputManager = im;defaultServiceManager()->addService(String16("inputflinger"), im);}static void nativeStart(JNIEnv* env, jobject nativeImplObj) {NativeInputManager* im = getNativeInputManager(env, nativeImplObj);status_t result = im->getInputManager()->start();if (result) {jniThrowRuntimeException(env, "Input manager could not be started.");}}
- NativeInputManager实现了InputReaderPolicyInterface,InputDispatcherPolicyInterface,PointerControllerPolicyInterface接口,
- serviceObj和looper分别赋值给mServiceObj和mLooper变量,后续可以通过mServiceObj调用Java层InputManagerService对象的方法了。
- 把自己作为参数实例化InputManager。
- 添加“inputflinger”到ServiceManager。
2.2 InputManager
InputManager初始化:
// InputManager.cppInputManager::InputManager(const sp<InputReaderPolicyInterface>& readerPolicy,const sp<InputDispatcherPolicyInterface>& dispatcherPolicy) {mDispatcher = createInputDispatcher(dispatcherPolicy);mClassifier = std::make_unique<InputClassifier>(*mDispatcher);mBlocker = std::make_unique<UnwantedInteractionBlocker>(*mClassifier);mReader = createInputReader(readerPolicy, *mBlocker);}
InputManager定义了四个重要的变量,也是一个InputEvent的传递流程:
InputReader -> UnwantedInteractionBlocker -> InputClassifier -> InputDispatcher
- mReader:通过EventHub监听"/dev/input"事件。
- mBlocker:拦截不需要的事件。
- mClassifier:对事件分类。
- mDispatcher:分发事件。
其中mReader和mDispatcher还传递了NativeInputManager对象参数,赋值到各自的mPolicy变量,后续可直接通过mPolicy调用Java层InputMangerService对象方法。
初始化流程大概就是这样,接着1.2 start()开始启动InputManger。
// InputManager.cppstatus_t InputManager::start() {status_t result = mDispatcher->start();if (result) {ALOGE("Could not start InputDispatcher thread due to error %d.", result);return result;}result = mReader->start();if (result) {ALOGE("Could not start InputReader due to error %d.", result);mDispatcher->stop();return result;}return OK;}
调用mDispatcher和mReader各自start()方法。
2.2.1 事件传递
事件的传递流程是:InputReader -> UnwantedInteractionBlocker -> InputClassifier -> InputDispatcher
但是查看各个类结构,并没有看到其中相互关联了,原因是使用了代理设计模式:
QueuedListener,UnwantedInteractionBlocker,InputClassifier,InputDispatcher都实现了InputListenerInterface接口,他们都是输入事件的监听者,输入事件的链式传递就是通过QueuedListener实现的,这里使用了代理设计模式,代理对象是InputListenerInterface。
InputListenerInterface定义了事件监听接口:
// InputListener.hclass InputListenerInterface {public:virtual void notifyConfigurationChanged(const NotifyConfigurationChangedArgs* args) = 0;virtual void notifyKey(const NotifyKeyArgs* args) = 0;virtual void notifyMotion(const NotifyMotionArgs* args) = 0;virtual void notifySwitch(const NotifySwitchArgs* args) = 0;virtual void notifySensor(const NotifySensorArgs* args) = 0;virtual void notifyVibratorState(const NotifyVibratorStateArgs* args) = 0;virtual void notifyDeviceReset(const NotifyDeviceResetArgs* args) = 0;virtual void notifyPointerCaptureChanged(const NotifyPointerCaptureChangedArgs* args) = 0;};
为了实现优雅的链式调用,QueuedListener内部持有一个InputListenerInterface实例化对象mInnerListener,和一个vector mArgsQueue管理所有输入事件,flush()方法遍历mArgsQueue所有输入事件,将其传递给mInnerListener,也就是下一个环节:
// InputListener.hclass QueuedInputListener : public InputListenerInterface {public:void flush();private:InputListenerInterface& mInnerListener;std::vector<std::unique_ptr<NotifyArgs>> mArgsQueue;};// InputListner.cppQueuedInputListener::QueuedInputListener(InputListenerInterface& innerListener): mInnerListener(innerListener) {}void QueuedInputListener::flush() {for (const std::unique_ptr<NotifyArgs>& args : mArgsQueue) {args->notify(mInnerListener);}mArgsQueue.clear();}
而InputReader,UnwantedInteractionBlocker,InputClassifier都只需要持有QueuedInputListener引用就好了,类设计者不必关心下个环节具体是谁,只需要在处理事件后调用QueuedInputListener.flush()就可以把任务传递下去。
class InputReader : public InputReaderInterface {private:QueuedInputListener mQueuedListener;}class UnwantedInteractionBlocker : public UnwantedInteractionBlockerInterface {private:QueuedInputListener mQueuedListener;}class InputClassifier : public InputClassifierInterface {private:QueuedInputListener mQueuedListener;}
InputManager初始化时实例化了以上对象,构造方法中传递mQueuedListener参数,在实例化的过程中确定了调用链环节。
三、InputReader
mReader = createInputReader(readerPolicy, *mBlocker);初始化InputReader。
// InputReaderFactory.cppstd::unique_ptr<InputReaderInterface> createInputReader(const sp<InputReaderPolicyInterface>& policy, InputListenerInterface& listener) {return std::make_unique<InputReader>(std::make_unique<EventHub>(), policy, listener);}
InputReaderFactory实例化了一个EventHub对象传递给InputReader构造方法。
3.1 EventHub
// EventHub.cppEventHub::EventHub(void): mBuiltInKeyboardId(NO_BUILT_IN_KEYBOARD),mNextDeviceId(1),mControllerNumbers(),mNeedToSendFinishedDeviceScan(false),mNeedToReopenDevices(false),mNeedToScanDevices(true),mPendingEventCount(0),mPendingEventIndex(0),mPendingINotify(false) {ensureProcessCanBlockSuspend();// 1.创建一个新的epoll实例mEpollFd = epoll_create1(EPOLL_CLOEXEC);LOG_ALWAYS_FATAL_IF(mEpollFd < 0, "Could not create epoll instance: %s", strerror(errno));// 2.创建一个新的inotify实例,Inotify API用于检测文件系统变化的机制。Inotify可用于检测单个文件,也可以检测整个目录。// 当目录下的设备节点发生增删事件时,可已通过 read(fd) 获取事件的详细信息mINotifyFd = inotify_init1(IN_CLOEXEC);std::error_code errorCode;bool isDeviceInotifyAdded = false;// 3.添加 /dev/input 或者 /dev 目录的Inotifyif (std::filesystem::exists(DEVICE_INPUT_PATH, errorCode)) {addDeviceInputInotify();} else {addDeviceInotify();isDeviceInotifyAdded = true;}struct epoll_event eventItem = {};eventItem.events = EPOLLIN | EPOLLWAKEUP;eventItem.data.fd = mINotifyFd;// 4. 把 inotify 添加到 epoll 监听队列中,当 inotify 事件到来时,epoll_wait() 会// 立即返回,EventHub 可以从 fd 中读取设备节点的增删信息并进行处理int result = epoll_ctl(mEpollFd, EPOLL_CTL_ADD, mINotifyFd, &eventItem);// 5. 创建管道,fds[0] 表示管道的读端,fds[1] 表示管道的写端int wakeFds[2];result = pipe2(wakeFds, O_CLOEXEC);mWakeReadPipeFd = wakeFds[0];mWakeWritePipeFd = wakeFds[1];// 设置唤醒读端为非阻塞式result = fcntl(mWakeReadPipeFd, F_SETFL, O_NONBLOCK);// 设置唤醒写端为非阻塞式result = fcntl(mWakeWritePipeFd, F_SETFL, O_NONBLOCK);//6. 把唤醒读端的 fd 添加到 epoll 监听队列中,目的是在必要时唤醒 reader 线程eventItem.data.fd = mWakeReadPipeFd;result = epoll_ctl(mEpollFd, EPOLL_CTL_ADD, mWakeReadPipeFd, &eventItem);}
EventHub采用INotify + epoll机制实现监听目录/dev/input下的设备节点,后续inputReader的loopOnce循环调用EventHub::getEvents()方法,解析数据封装为RawEvent对象。
3.2 InputReader::start
// InputReader.cppstatus_t InputReader::start() {if (mThread) {return ALREADY_EXISTS;}mThread = std::make_unique<InputThread>("InputReader", [this]() { loopOnce(); }, [this]() { mEventHub->wake(); });return OK;}status_t InputReader::stop() {if (mThread && mThread->isCallingThread()) {ALOGE("InputReader cannot be stopped from its own thread!");return INVALID_OPERATION;}mThread.reset();return OK;}
1.1NativeImpl完成初始化后,1.2 mNative.start()调用InputManager::start()启动InputDispatcher和InputReader。
Start()启动"InputReader"线程,threadLoop()中循环调用loopOnce(),stop()方法调用mThread.reset(),执行mEventHub->wake()。
3.3 InputReader::loopOnce
// InputReader.cppvoid InputReader::loopOnce() {// 1. 通过EventHub读取输入事件size_t count = mEventHub->getEvents(timeoutMillis, mEventBuffer, EVENT_BUFFER_SIZE);{std::scoped_lock _l(mLock);mReaderIsAliveCondition.notify_all();// 2. 处理输入事件if (count) {processEventsLocked(mEventBuffer, count);}}// 3. 清空mQueuedListener,将事件传递给 mBlocker(UnwantedInteractionBlocker)处理mQueuedListener.flush();}
loopOnce()方法包含了inputReader最主要的运行逻辑,先通过EventHub::getEvents()读取解析/dev/input节点下的事件,processEventsLocked()根据类型处理事件,最后通过QueuedListener传递给下一环,也就是mBlocker(UnwantedInteractionBlocker对象)。
3.3.1 EventHub::getEvents
size_t EventHub::getEvents(int timeoutMillis, RawEvent* buffer, size_t bufferSize) {RawEvent* event = buffer;for (;;) {// 1. 输入设备移除事件for (auto it = mClosingDevices.begin(); it != mClosingDevices.end();) {event->type = DEVICE_REMOVED;}// 2. 输入设备添加事件while (!mOpeningDevices.empty()) {event->type = DEVICE_ADDED;}// 3. 输入设备扫描完成事件if (mNeedToSendFinishedDeviceScan) {event->type = FINISHED_DEVICE_SCAN;}// 4. 输入事件while (mPendingEventIndex < mPendingEventCount) {if (eventItem.events & EPOLLIN) {event->when = processEventTimestamp(iev);event->readTime = systemTime(SYSTEM_TIME_MONOTONIC);event->deviceId = deviceId;event->type = iev.type;event->code = iev.code;event->value = iev.value;event += 1;capacity -= 1;}}int pollResult = epoll_wait(mEpollFd, mPendingEventItems, EPOLL_MAX_EVENTS, timeoutMillis);mPendingEventCount = size_t(pollResult);}}
EventHub通过epoll读取输入事件,封装成RawEvent对象,event->type区分事件类型。
3.3.2 InputReader::processEventsLocked
void InputReader::processEventsLocked(const RawEvent* rawEvents, size_t count) {for (const RawEvent* rawEvent = rawEvents; count;) {int32_t type = rawEvent->type;size_t batchSize = 1;// 1.输入事件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;}processEventsForDeviceLocked(deviceId, rawEvent, batchSize);} else {switch (rawEvent->type) {// 2.输入设备添加事件,InputDevicecase EventHubInterface::DEVICE_ADDED:addDeviceLocked(rawEvent->when, rawEvent->deviceId);break;// 3.输入设备移除事件case EventHubInterface::DEVICE_REMOVED:removeDeviceLocked(rawEvent->when, rawEvent->deviceId);break;// 4.输入设备扫描完成事件case EventHubInterface::FINISHED_DEVICE_SCAN:handleConfigurationChangedLocked(rawEvent->when);break;default:ALOG_ASSERT(false); // can't happenbreak;}}count -= batchSize;rawEvent += batchSize;}}
从EventHub获取到封装好的RawEvent后,RawEvent保存了事件的原始数据,并没有对事件进行细致的解析,设备添加事件也是一个RawEvent,还有比如用户输入事件,键盘、鼠标、传感器等事件在这里都没有被区分开,processEventsLocked()对原始事件进行处理。
3.3.2.1设备添加事件
先看下设备添加事件DEVICE_ADDED的处理流程:
inputflinger定义了InputDevice类描述输入设备对象,InputMapper把原始事件RawEvent解析成具体对应事件的参数,InputMapper的具体实现类有:
- CursorInputMapper
- KeyboardInputMapper
- TouchInputMapper
- SensorInputMapper
等等。
addDeviceLocked()调用createDeviceLocked()创建一个InputDevice对象,device->addEventHubDevice(eventHubId)将InputDevice和InputMapper实现类关联起来,添加到mDevices变量管理。
// InputDevice.hprivate:std::unordered_map<int32_t, DevicePair> mDevices;// InputDevice.cppvoid InputDevice::addEventHubDevice(int32_t eventHubId, bool populateMappers) {// mappersstd::vector<std::unique_ptr<InputMapper>> mappers;if (classes.test(InputDeviceClass::KEYBOARD)) {keyboardSource |= AINPUT_SOURCE_KEYBOARD;}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));}// 添加到 mDevicesmDevices.insert({eventHubId, std::make_pair(std::move(contextPtr), std::move(mappers))});}
3.3.2.2 输入事件
对于输入事件,inputReader调用processEventsForDeviceLocked()方法处理:
// InputReader.cppvoid InputReader::processEventsForDeviceLocked(int32_t eventHubId, const RawEvent* rawEvents,size_t count) {auto deviceIt = mDevices.find(eventHubId);device->process(rawEvents, count);}
mDevices管理着所有输入设备,找到对应的输入设备调用process()方法。
// InputDevice.cppvoid InputDevice::process(const RawEvent* rawEvents, size_t count) {for (const RawEvent* rawEvent = rawEvents; count != 0; rawEvent++) {for_each_mapper_in_subdevice(rawEvent->deviceId, [rawEvent](InputMapper& mapper) {mapper.process(rawEvent);});}}
InputDevice也是从mDevices变量找到对应的InputMapper对象,交给mapper.process(rawEvent);处理。接下来就是InputMapper的各种实现类解析RawEvent数据了,这里我们关注键盘输入KeyboardInputMapper实现类。
KeyboardInputMapper剔除多余不感兴趣的数据,KeyboardInputMapper::processKey()将数据解析封装成一个NotifyKeyArgs对象,交给下一个环节:
// KeyboardInputMapper.cppvoid KeyboardInputMapper::process(const RawEvent* rawEvent) {switch (rawEvent->type) {case EV_KEY: {if (isKeyboardOrGamepadKey(scanCode)) {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) {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);getListener().notifyKey(&args);}
getListener()返回的是InputReader的mQueuedListener对象。
// InputListener.cppvoid QueuedInputListener::notifyConfigurationChanged(const NotifyConfigurationChangedArgs* args) {traceEvent(__func__, args->id);mArgsQueue.emplace_back(std::make_unique<NotifyConfigurationChangedArgs>(*args));}
2.2.1小节中提到过,InputListener.mArgsQueue是一个vector数组,保存管理着loopOnce()执行一次读取的所有输入事件,刚解析的键盘输入事件被添加到mArgsQueue变量。
3.3.3 mQueuedListener.flush()
事件的读取解析都完成了,接下来InputReader将处理流程交给下一个环节UnwantedInteractionBlocker了。
// InputListener.cppvoid QueuedInputListener::flush() {for (const std::unique_ptr<NotifyArgs>& args : mArgsQueue) {args->notify(mInnerListener);}mArgsQueue.clear();}void NotifyKeyArgs::notify(InputListenerInterface& listener) const {listener.notifyKey(this);}
这里的mInnerListener就是mBlocker,交给mBlocker的notifyKey()方法处理后,清空数组mArgsQueue。
mBlocker将事件传递给mClassifier,mClassifier将事件传递给mDispatcher。
四、InputDispatcher
4.1 InputDispatcher::notifyKey
键盘输入事件传递到InputDispatcher::notifyKey()。
// InputDispatcher.hstd::deque<std::shared_ptr<EventEntry>> mInboundQueue GUARDED_BY(mLock);// InputDispatcher.cppvoid InputDispatcher::notifyKey(const NotifyKeyArgs* args) {// 1.封装成 KeyEventKeyEvent event;event.initialize(args->id, args->deviceId, args->source, args->displayId, INVALID_HMAC,args->action, flags, keyCode, args->scanCode, metaState, repeatCount,args->downTime, args->eventTime);// 2.在event事件入队前处理mPolicy->interceptKeyBeforeQueueing(&event, /*byref*/ policyFlags);{mLock.lock();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);// 3.event入队needWake = enqueueInboundEventLocked(std::move(newEntry));mLock.unlock();}// 4.唤醒 mLooperif (needWake) {mLooper->wake();}}
notifyKey主要做了四件事:
- EventHub将事件读取解析为RawEvent,KeyboardInputMapper将RawEvent封装成NotifyKeyArgs,事件传递到InputDispatcher,终于被封装成了KeyEvent对象。
- InputDispatcher持有mInboundQueue变量,管理所有到达需要处理的事件,使用EventEntry对象描述,所有需要分发的事件都被封装成EventEntry入队到mInboundQueue。这里在入队之前调用了interceptKeyBeforeQueueing()方法,在事件被设备读取之前先进行一些处理,比如power按键需要对应用程序的生命周期处理,2.2小节提到过,InputDispatcher和InputReader都各自持有mPolicy对象,实际实现是NativeInputManger对象,这样就可以调用Java层的InputMangerService方法了,最终调用到熟悉的PhoneWindowManger.interceptKeyBeforeQueueing()。
// InputManagerCallback.java/*** Provides an opportunity for the window manager policy to intercept early key* processing as soon as the key has been read from the device.*/@Overridepublic int interceptKeyBeforeQueueing(KeyEvent event, int policyFlags) {return mService.mPolicy.interceptKeyBeforeQueueing(event, policyFlags);}
- 封装成EventEntry入队。
- 唤醒mLooper开始处理事件分发。
4.2 InputDispatcher::start
2.2小节中,InputManager::start()分别调用了InputDispatcher和InputReader的start()方法,之前已经分析了InputReader.start(),现在看下InputDispatcher.start()的启动过程。
// InputDispathcer.husing Command = std::function<void()>;std::deque<Command> mCommandQueue GUARDED_BY(mLock);// InputDispatcher.cppstatus_t InputDispatcher::start() {if (mThread) {return ALREADY_EXISTS;}mThread = std::make_unique<InputThread>("InputDispatcher", [this]() { dispatchOnce(); }, [this]() { mLooper->wake(); });return OK;}
启动"InputDispatcher"线程,循环调用dispatchOnce()方法。
4.3 InputDispatcher::dispatchOnce
// InputDispatcher.cppvoid InputDispatcher::dispatchOnce() {nsecs_t nextWakeupTime = LONG_LONG_MAX;{std::scoped_lock _l(mLock);mDispatcherIsAlive.notify_all();// 1. 如果mCommandQueue没有待处理的Command,则执行dispatchOnceInnerLocked去产生Commandif (!haveCommandsLocked()) {dispatchOnceInnerLocked(&nextWakeupTime);}//2. 如果mCommandQueue队列消息不为空,则循环从中取出Command进行处理if (runCommandsLockedInterruptable()) {nextWakeupTime = LONG_LONG_MIN;}// 3.判断是否要触发ANRconst nsecs_t nextAnrCheck = processAnrsLocked();nextWakeupTime = std::min(nextWakeupTime, nextAnrCheck);if (nextWakeupTime == LONG_LONG_MAX) {mDispatcherEnteredIdle.notify_all();}}nsecs_t currentTime = now();int timeoutMillis = toMillisecondTimeoutDelay(currentTime, nextWakeupTime);// 4. mLooper睡眠等待时间timeoutMillismLooper->pollOnce(timeoutMillis);}
mCommandQueue队列变量管理Command对象,Command实际指向一个函数std::function<void()>,执行一些必要特殊的操作,通知Java层的InputMangerService,比如焦点改变:sendFocusChangedCommandLocked(),ANR发生:onAnrLocked()等等。
4.3.1 dispatchOnceInnerLocked
事件的分发逻辑在dispatchOnceInnerLocked()实现:
// InputDispatcher.cppvoid InputDispatcher::dispatchOnceInnerLocked(nsecs_t* nextWakeupTime) {// 1.当前没有在等待的事件,从mInboundQueue获取。if (!mPendingEvent) {mPendingEvent = mInboundQueue.front();mInboundQueue.pop_front();}// 2.根据type分别处理switch (mPendingEvent->type) {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;}done = dispatchMotionLocked(currentTime, motionEntry, &dropReason, nextWakeupTime);break;}}}
mPendingEvent保存当前处理的事件,没有的话从mInboundQueue队列中取出,4.1小节enqueueInboundEventLocked()方法,键盘输入事件就被封装成EventEntry入队到mInboundQueue队列中,后续将在这里被处理。
这里我们关心MOTION触屏输入事件,继续交给dispatchMotionLocked()处理。
4.3.2 dispatchMotionLocked
// InputDispatcher.cppbool InputDispatcher::dispatchMotionLocked(nsecs_t currentTime, std::shared_ptr<MotionEntry> entry,DropReason* dropReason, nsecs_t* nextWakeupTime) {const bool isPointerEvent = isFromSource(entry->source, AINPUT_SOURCE_CLASS_POINTER);// Identify targets.std::vector<InputTarget> inputTargets;if (isPointerEvent) {// Pointer event. (eg. touchscreen)injectionResult =findTouchedWindowTargetsLocked(currentTime, *entry, inputTargets, nextWakeupTime,&conflictingPointerActions);} else {// Non touch event. (eg. trackball)injectionResult =findFocusedWindowTargetsLocked(currentTime, *entry, inputTargets, nextWakeupTime);}dispatchEventLocked(currentTime, entry, inputTargets);return true;}
isPointerEvent区分是触摸屏幕还是轨迹球,InputTarget具体说明了输入事件如何分发到具体的window上,其中保存了数据传输路径InputChannel等。
为了找到正确的焦点窗口,mFocusedApplicationHandlesByDisplay变量保存了当前持有焦点的App,每启动一个新的App,焦点App都会通过InputMonitor更新,InputMonitor在View的显示过程中被初始化:https://blog.csdn.net/qq_36063677/article/details/129908973:
// InputMonitor.javavoid setFocusedAppLw(ActivityRecord newApp) {// Focused app has changed.mService.mInputManager.setFocusedApplication(mDisplayId,newApp != null ? newApp.getInputApplicationHandle(true /* update */) : null);}// InputDispatcher.cpp// Focused applications.std::unordered_map<int32_t, std::shared_ptr<InputApplicationHandle>>mFocusedApplicationHandlesByDisplay GUARDED_BY(mLock);
mFocusedWindowTokenByDisplay变量保存了各个Display设备(考虑到多个显示设备的情况)当前的焦点Window,由surfaceflinger进程负责更新:
// SurfaceFlinger.cppvoid SurfaceFlinger::updateInputFlinger() {for (const auto& focusRequest : inputWindowCommands.focusRequests) {inputFlinger->setFocusedWindow(focusRequest);}}// FocusResolver.hstd::unordered_map<int32_t /* displayId */, NamedToken> mFocusedWindowTokenByDisplay;
对于触摸屏幕,findTouchedWindowTargetsLocked()对分屏的使用情景进行了适配,isSplit变量标识当前是否处于分屏状态。
找到了正确的inputTargets后,dispatchEventLocked(currentTime, entry, inputTargets);继续分发过程。
4.3.3 dispatchEventLocked
// InputDispatcher.cppvoid InputDispatcher::dispatchEventLocked(nsecs_t currentTime,std::shared_ptr<EventEntry> eventEntry,const std::vector<InputTarget>& inputTargets) {for (const InputTarget& inputTarget : inputTargets) {sp<Connection> =getConnectionLocked(inputTarget.inputChannel->getConnectionToken());if (connection != nullptr) {prepareDispatchCycleLocked(currentTime, connection, eventEntry, inputTarget);}}}
getConnectionLocked()方法通过InputChannel的token获取链接Connection对象,mConnectionsByToken是一个map变量,InputDispatcher维护mConnectionsByToken变量,保存所有当前连接的Connection,key值是token,Binder类型。关于InputChanel的建立,参考下一章节。
接下来prepareDispatchCycleLocked()调用enqueueDispatchEntriesLocked()方法:
4.3.4 enqueueDispatchEntriesLocked
void InputDispatcher::enqueueDispatchEntriesLocked(nsecs_t currentTime,const sp<Connection>& connection,std::shared_ptr<EventEntry> eventEntry,const InputTarget& inputTarget) {// 1. 添加分发条目到队列连接对象 connectionenqueueDispatchEntryLocked(connection, eventEntry, inputTarget,InputTarget::FLAG_DISPATCH_AS_HOVER_EXIT);enqueueDispatchEntryLocked(connection, eventEntry, inputTarget,InputTarget::FLAG_DISPATCH_AS_OUTSIDE);enqueueDispatchEntryLocked(connection, eventEntry, inputTarget,InputTarget::FLAG_DISPATCH_AS_HOVER_ENTER);enqueueDispatchEntryLocked(connection, eventEntry, inputTarget,InputTarget::FLAG_DISPATCH_AS_IS);enqueueDispatchEntryLocked(connection, eventEntry, inputTarget,InputTarget::FLAG_DISPATCH_AS_SLIPPERY_EXIT);enqueueDispatchEntryLocked(connection, eventEntry, inputTarget,InputTarget::FLAG_DISPATCH_AS_SLIPPERY_ENTER);// 2. 开始分发if (wasEmpty && !connection->outboundQueue.empty()) {startDispatchCycleLocked(currentTime, connection);}}
enqueueDispatchEntryLocked()添加分发条目到队列连接对象Connection,然后开始分发工作,查看enqueueDispatchEntryLocked()具体实现:
4.3.4.1 enqueueDispatchEntryLocked
void InputDispatcher::enqueueDispatchEntryLocked(const sp<Connection>& connection,std::shared_ptr<EventEntry> eventEntry,const InputTarget& inputTarget,int32_t dispatchMode) {// 1. 封装 DispatchEntry对象 std::unique_ptr<DispatchEntry> dispatchEntry =createDispatchEntry(inputTarget, eventEntry, inputTargetFlags);// 2. 添加到 connection->outboundQueue队列connection->outboundQueue.push_back(dispatchEntry.release());}
在这里EventEntry又被解析封装成DispatchEntry对象,专门用于分发工作。
回到分发流程startDispatchCycleLocked()。
4.3.4.2 startDispatchCycleLocked
void InputDispatcher::startDispatchCycleLocked(nsecs_t currentTime,const sp<Connection>& connection) {while (connection->status == Connection::Status::NORMAL && !connection->outboundQueue.empty()) {DispatchEntry* dispatchEntry = connection->outboundQueue.front();switch (eventEntry.type) {case EventEntry::Type::MOTION: {// Publish the motion event.status = connection->inputPublisher.publishMotionEvent(dispatchEntry->seq,dispatchEntry->resolvedEventId,motionEntry.deviceId, motionEntry.source,motionEntry.displayId, std::move(hmac),dispatchEntry->resolvedAction,motionEntry.actionButton,dispatchEntry->resolvedFlags,motionEntry.edgeFlags, motionEntry.metaState,motionEntry.buttonState,motionEntry.classification,dispatchEntry->transform,motionEntry.xPrecision, motionEntry.yPrecision,motionEntry.xCursorPosition,motionEntry.yCursorPosition,dispatchEntry->rawTransform,motionEntry.downTime, motionEntry.eventTime,motionEntry.pointerCount,motionEntry.pointerProperties, usingCoords);break;}}connection->outboundQueue.erase(std::remove(connection->outboundQueue.begin(),connection->outboundQueue.end(),dispatchEntry));}}
从connection->outboundQueue不断取出DispatchEntry,调用connection->inputPublisher.publishMotionEvent()发送输入事件,分发完成后在outboundQueue中擦除对象。connection从InputChannel对象获取,InputChannel描述了inputflinger和事件接受对象的连接,那么InputChannel是怎么建立的呢,在(InputChannel文章)继续分析。