天天看点

06.输入系统:第10课第13节_输入系统_Dispatcher线程_分发dispatch

该小节我们讲解,Dispatcher线程是如何分发事件的,在这之前,我们先回顾一下之前的学习,下面是一个框图:

06.输入系统:第10课第13节_输入系统_Dispatcher线程_分发dispatch

在前面已经分析过,Dispatcher线程会对数据进行一些处理之后,再分发出去。他首先会把输入事件分为类(如:Global,System,user等等,对于Global,System处理完之后会直接抛弃,user类会加入队列,然后分发给应用程序。分发过程一般如下:1.查找目标APP,得到connection。2,把输入事件放入对应connection的mOutBoundQueue队列,然后进行分发。

在上小节的视频中,我们可以知道Dispatcher线程线程中,存在mConnectionsByFd,里面存在多个connection,每个connection中包括了 inputChannel, inputChannel中又包括了fd1,并且在对应的APP中,存在相应的fd2,这两个fd来源于

SocketPair,下面是他的主要步骤:

1.查找目标:向WindowManagerService查询当前窗口,获得对应的connection。

2.把输入事件放入connection中的mOutBoundQueue队列。

3.从队列中取出事件逐个写入到文件句柄中。(这样,另外一边的APP就能从对应的fd中读取事件)

下面我们就根据上述的几个步骤分析源代码

源码分析

在前面的讲解中,都是依照按键的流程进行分析,已经分析到了InputDispatcher.cpp中的dispatchKeyLocked函数,该函数对输入事件进行稍微的处理之后,就会进行分发:

InputDispatcher::dispatchKeyLocked()
	injectionResult = findFocusedWindowTargetsLocked(currentTime,entry, inputTargets, nextWakeupTime);//查找目标窗口
	 	if (mFocusedWindowHandle == NULL) {//该变量表示最外面的窗口运行程序,该处不去分析其内部是如何设置
	 		...............................//获取最外面的窗口
	 	if (! checkInjectionPermission(mFocusedWindowHandle, entry->injectionState)) {//权限检查
	 	/*使用mFocusedWindowHandle构建一个InputTarget*/
	 	addWindowTargetLocked(mFocusedWindowHandle,InputTarget::FLAG_FOREGROUND | InputTarget::FLAG_DISPATCH_AS_IS,BitSet32(0),inputTargets);
	 		 /*核心:把查询到的inputChannel赋值给 target.inputChannel*/
	 		 target.inputChannel = windowInfo->inputChannel;
	 dispatchEventLocked(currentTime, entry, inputTargets);//发送事件
	 	ssize_t connectionIndex = getConnectionIndexLocked(inputTarget.inputChannel);//获取fd的索引
	 	/*根据fd的索引提取对应的connection*/
		sp<Connection> connection = mConnectionsByFd.valueAt(connectionIndex);
		prepareDispatchCycleLocked(currentTime, connection, eventEntry, &inputTarget);
			/*把事件(多个)放入队列*/
			enqueueDispatchEntriesLocked(currentTime, connection, eventEntry, inputTarget);
				enqueueDispatchEntryLocked()
					/*把dispatchEntry(某个事件)放入到connection的队列的尾部*/
					connection->waitQueue.enqueueAtTail(dispatchEntry);
				/*从队列取出事件,写入到对应的文件句柄之中*/
				startDispatchCycleLocked(currentTime, connection);
					/*从队列头部取出一个事件*/
					DispatchEntry* dispatchEntry = connection->outboundQueue.head;
						case EventEntry::TYPE_KEY: {//如果为按键事件
							connection->inputPublisher.publishKeyEvent()//发送事件
								mChannel->sendMessage(&msg);//构建一个msg,调用该函数发送
									/*写入到mFd中,对应的应用程序,马上就能读取到事件*/
									nWrite = ::send(mFd, msg, msgLength, MSG_DONTWAIT | MSG_NOSIGNAL);
    } while (nWrite == -1 && errno == EINTR);
           

函数调用到send(),Dispatcher线程基本完成了他的使命,剩下的就是应用程序的事情了。上述函数的详细调用框图如下:

06.输入系统:第10课第13节_输入系统_Dispatcher线程_分发dispatch

继续阅读