Android inputflinger系统分析

news/2025/1/14 5:22:03/

本文基于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.");}}
  1. NativeInputManager实现了InputReaderPolicyInterface,InputDispatcherPolicyInterface,PointerControllerPolicyInterface接口,
  2. serviceObj和looper分别赋值给mServiceObj和mLooper变量,后续可以通过mServiceObj调用Java层InputManagerService对象的方法了。
  3. 把自己作为参数实例化InputManager。
  4. 添加“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文章)继续分析。


http://www.ppmy.cn/news/61102.html

相关文章

组件等比例放大——scale和zoom

scale和zoom的区别 zoom的缩放是相对于左上角的&#xff1b;而scale默认是居中缩放&#xff0c;可以通过transform-origin修改基准点zoom的缩放改变了元素占据的空间大小&#xff1b;而scale的缩放占据的原始尺寸不变&#xff0c;页面布局不会发生变化。对文字的缩放规则不一致…

Vben Admin 自学记录 —— Drawer组件的基本使用及练习(持续更新中...)

Drawer 抽屉组件 对 antv 的 drawer 组件进行封装&#xff0c;扩展拖拽&#xff0c;全屏&#xff0c;自适应高度等功能。 Drawer相关使用及概念 练习 —— 在之前table基础上&#xff0c;添加查看功能&#xff0c;点击查看按钮&#xff0c;弹出抽屉显示单条表格数据&#xf…

浏览器安全之XSS跨站脚本

基本概念 跨站脚本&#xff08;Cross-Site Scripting&#xff0c;XSS&#xff09;是一种经常出现在Web应用程序中的计算机安全漏洞&#xff0c;是由于Web应用程序对用户的输入过滤不足而产生的。 攻击者利用网站漏洞把恶意的脚本代码&#xff08;通常包括HTML代码和客户端Javas…

Unity 后处理(Post-Processing) -- (2)创建后处理配置文件

通过前面一小节&#xff0c;我们初步认识了后处理是什么&#xff0c;在Unity中简单的试了试后处理的效果。本节我们来创建一个我们自己的后处理配置文件&#xff08;post-processing profile&#xff09;。 一个后处理配置文件包含了一系列为了达到特定视觉效果的后处理效果的配…

Istio注入SideCar原理

简介 Istio提供一种简单的方式来建立已部署的服务的网络&#xff0c;具备负载均衡&#xff0c;服务到服务认证&#xff0c;监控等等功能&#xff0c;而不需要改动任何服务代码。 简单的说&#xff0c;有了Istio&#xff0c;你的服务就不再需要任何微服务开发框架&#xff08;典…

【AWS入门】AWS CICD

目录 一 .TASK二. 环境准备IAM创建存储库ec2-repoec2-wp 三. Code Deploy创建应用程序创建部署组创建管道部署后的ec2-wp 一 .TASK 创建2台EC2实例&#xff0c;一台名为「ec2-repo」&#xff0c;用作开发环境&#xff0c;将编写好的代码提交至repository(需安装git)&#xff0…

最优化方法Python计算:一元函数搜索算法——二分法

设一元目标函数 f ( x ) f(x) f(x)在区间 [ a 0 , b 0 ] ⊆ R [a_0,b_0]\subseteq\text{R} [a0​,b0​]⊆R&#xff08;其长度记为 λ \lambda λ&#xff09;上为单峰函数&#xff0c;且在 ( a 0 , b 0 ) (a_0,b_0) (a0​,b0​)内连续可导&#xff0c;即其导函数 f ′ ( x ) f…

凌恩生物美文分享|HGTree v2.0:水平基因转移数据库

水平基因转移(HGT)是指遗传物在物种间从一个相邻生物体到另一个生物体横向传递&#xff0c;是原核生物遗传变异的重要过程。HGT是负责塑造原核生物基因组和在自然选择中生存的驱动力之一&#xff0c;对原核生物的进化有很大贡献&#xff0c;但它会使物种进化史复杂化&#xff0…