==============================================================================
前文讲到android的事件处理系统,这里称为事件传递系统更贴切一些,因为android事件系统中比较复杂就是其传递过程,下面我们就以事件传递系统来代替事件处理系统。android事件传递系统是以共享内存和管道的进程间通信方式来实现传递的,为了便于理解它的传递机制,事件传递系统的初始化工作的理解则会显得非常的重要。
事件传递系统中的管道的主要作用是在有事件被存储到共享内存中时,system_server端通知ViewRoot去读取事件的通信机制。既然是ViewRoot和system_server之间建立管道通信,那么ViewRoot和WindowManagerService(负责事件传递,运行在system_server进程中)各需维护管道的一个文件描述符,其实ViewRoot和WindowManagerService不是各维护了一个管道的文件描述符,而是两个,当然了这两个描述符不属于同一管道,实际上也就是ViewRoot和WindowManagerService之间实现了全双工的管道通信。
WindowManagerService—>ViewRoot方向的管道通信,表示WMS通知ViewRoot有新事件被写入到共享内存;
ViewRoot–>WindowManagerService方向的管道通信,表示ViewRoot已经消化完共享内存中的新事件,特此通知WMS。
ViewRoot和WindowManagerService的管道的文件描述符都是被存储在一个名为InputChannel的类中,这个InputChannel类是管道通信的载体。
首先来看ViewRoot端的管道的建立。
setView()@ViewRoot.java
[java] view plain copy
-
requestLayout();
-
mInputChannel = new InputChannel();
-
try {
-
res = sWindowSession.add(mWindow, mWindowAttributes,
-
getHostVisibility(), mAttachInfo.mContentInsets,
-
mInputChannel);
-
} catch (RemoteException e) {
在ViewRoot和WMS(WindowManagerService)建立起连接之前首先会创建一个InputChannel对象,同样的WMS端也会创建一个InputChannel对象,不过WMS的创建过程是在ViewRoot调用add()方法时调用的。InputChannel的构造不做任何操作,所以在ViewRoot中创建InputChannel时尚未初始化,它的初始化过程是在调用WMS方法add()时进行的,看到上面代码中将mInputChannel作为参数传递给WMS,目的就是为了初始化。下面转到WMS代码看看InputChannel的初始化过程。
addWindow()@WindowManagerService.java
[java] view plain copy
-
if (outInputChannel != null) {
-
String name = win.makeInputChannelName();
-
InputChannel[] inputChannels = InputChannel.openInputChannelPair(name);
-
win.mInputChannel = inputChannels[0];
-
inputChannels[1].transferToBinderOutParameter(outInputChannel);
-
mInputManager.registerInputChannel(win.mInputChannel);
-
}
outInputChannel为ViewRoot传递来的InputChannel对象,上述代码主要的工作其实就是创建一对InputChannel,这一对InputChannel中实现了一组全双工管道。 在创建InputChannel对的同时,会申请共享内存,并向2个InputChannel对象中各自保存一个共享内存的文件描述符。InputChannel创建完成后,会将其中一个的native InputChannel 赋值给outInputChannel,也就是对ViewRoot端InputChannel对象的初始化,这样随着ViewRoot和WMS两端的InputChannel对象的创建,事件传输系统的管道通信也就建立了起来。
创建InputChannel pair的过程以及管道建立,共享内存申请的过程就不再列出它的代码了,请参考openInputChannelPair()@InputTransport.cpp。下图为ViewRoot和WMS两端创建InputChannel pair之后的结构。