9.2.5 CommandListener模块分析
最后更新于:2022-04-02 05:53:21
Vold使用CL模块的流程是:
· 使用new创建一个CommandListener对象;
· 调用CL的startListener函数。
来看这两个函数。
1. 创建CommandListener的分析
和NetlinkerHandler一样,CommandListener也有一个相对不简单的派生关系,它的家族图谱如图9-5所示:
:-: ![](http://img.blog.csdn.net/20150802164411883?watermark/2/text/aHR0cDovL2Jsb2cuY3Nkbi5uZXQv/font/5a6L5L2T/fontsize/400/fill/I0JBQkFCMA==/dissolve/70/gravity/Center)
图9-5 CommandListener家族图谱
根据上图可以知道:
- CL定义了一些和Command相关的内部类,这里采用了设计模式中的Command模式,每个命令的处理函数都是runCommand。注意,上图只列出了部分Command类。
- CL也是从SocketListener派生的,不过它是Socket的监听(listen)端。
下面看它的代码:
**CommandListener.cpp**
~~~
CommandListener::CommandListener() :
FrameworkListener("vold") {
//CL模块支持的命令
registerCmd(new DumpCmd());
registerCmd(new VolumeCmd());
registerCmd(new AsecCmd());
registerCmd(new ShareCmd());
registerCmd(new StorageCmd());
registerCmd(new XwarpCmd());
}
/*
registerCmd函数将Command保存到mCommands中,mCommands的定义为一个列表,如下:
typedef android::ListFrameworkCommandCollection;
*/
voidFrameworkListener::registerCmd(FrameworkCommand *cmd) {
mCommands->push_back(cmd);
}
~~~
从上面的代码可知,CommandListener的基类是FrameworkListener,而FrameworkListener又从SocketListener类派生。之前在分析NM模块的NetLinkerHandler时,已介绍过SocketListener相关的知识了,所以此处不再赘述,只总结一下CL创建后的结果,它们是:
- CL会创建一个监听端的socket,这样就可以接收客户端的链接。
- 客户端发送命令给CL,CL则从mCommands中找到对应的命令,并交给该命令的runCommand函数处理。
下面来关注第二个函数startListener,这个函数由SocketListener实现。
2. startListener的分析和数据处理
其实在分析NetlinkerHandler时,已经介绍了startListener函数,这里再简单回顾一下,有些具体内容和本章对NetlinkerHandler的分析有关。
**SocketListener.cpp**
~~~
int SocketListener::startListener() {
if(!mSocketName && mSock == -1) {
......
errno = EINVAL;
return -1;
} else if (mSocketName) {
//mSOcketName为字符串“vold”。android_get_control_socket函数返回
//对应的socket句柄
if((mSock = android_get_control_socket(mSocketName)) < 0) {
......
return -1;
}
}
//CL模块是监听端
if(mListen && listen(mSock, 4) < 0) {
......
return -1;
} elseif (!mListen)
mClients->push_back(new SocketClient(mSock));
if(pipe(mCtrlPipe)) {
......
return -1;
}
//创建工作线程threadStart
if(pthread_create(&mThread, NULL, SocketListener::threadStart, this)) {
return -1;
}
return0;
}
~~~
当CL收到数据时,会调用onDataAvailable函数,它由FrameworkListener实现。
**FrameworkListener.cpp**
~~~
boolFrameworkListener::onDataAvailable(SocketClient *c) {
charbuffer[255];
intlen;
//读取数据
if((len = read(c->getSocket(), buffer, sizeof(buffer) -1)) < 0) {
......
return errno;
} elseif (!len)
return false;
intoffset = 0;
int i;
for (i= 0; i < len; i++) {
if(buffer[i] == '\0') {
//分发命令,最终会调用对应命令对象的runCommand进行函数处理。
dispatchCommand(c, buffer + offset);
offset = i + 1;
}
}
returntrue;
}
~~~
dispatchCommand最终会根据收到的命令名(如“Volume”,“Share”等)来调用对应的命令对象(如VolumeCmd,ShareCmd)的runCommand函数以处理请求。这一块非常简单,这里就不再详述了。
3. CL模块的总结
CL模块的主要工作是:
- 建立一个监听端的socket。
- 接收客户端的连接和请求,并调用对应Command对象的runComand函数处理。
目前,CL模块唯一的客户端就是MountService。来看看它。
';