在前一篇博客中介绍了个大体结构 Android—— 4.2 Vold挂载管理_主体构建 (一) ,按照代码的顺序结构来依次分析,这里来看看CommandListener这个类做了什么。



撰写不易,转载请注明出处:http://blog.csdn.net/jscese/article/details/38434263

一:CommandListener构造

在/system/vold/main.cpp的main函数中构建实例:


cl = new CommandListener();vm->setBroadcaster((SocketListener *) cl);nm->setBroadcaster((SocketListener *) cl);.../** Now that we're up, we can respond to commands*/if (cl->startListener()) {   SLOGE("Unable to start CommandListener (%s)", strerror(errno));   exit(1);}

源码位于/system/vold/CommandListener.cpp,构造函数如下:

CommandListener::CommandListener() :                 FrameworkListener("vold", true) {    registerCmd(new DumpCmd());    registerCmd(new VolumeCmd());    registerCmd(new AsecCmd());    registerCmd(new ObbCmd());    registerCmd(new StorageCmd());    registerCmd(new XwarpCmd());    registerCmd(new CryptfsCmd());}

构造一个父类FrameworkListener的实例

先看FrameworkListener的构造:

FrameworkListener::FrameworkListener(const char *socketName, bool withSeq) :                            SocketListener(socketName, true, withSeq) {    init(socketName, withSeq);}..void FrameworkListener::init(const char *socketName, bool withSeq) {    mCommands = new FrameworkCommandCollection();    errorRate = 0;    mCommandCount = 0;    mWithSeq = withSeq;}

可以看到传进去的"vold" 没在这个类里面起作用,是为了更高一层的构造,接着看/system/core/libsysutils/src/SocketListener.cpp中:


SocketListener::SocketListener(const char *socketName, bool listen, bool useCmdNum) {    init(socketName, -1, listen, useCmdNum);}void SocketListener::init(const char *socketName, int socketFd, bool listen, bool useCmdNum) {    mListen = listen;    mSocketName = socketName;    mSock = socketFd;    mUseCmdNum = useCmdNum;    pthread_mutex_init(&mClientsLock, NULL);    mClients = new SocketClientCollection();}
初始化线程锁mClientsLock,new 了一个SocketClient的容器mClients。

继承关系: CommandListener——>FrameworkListener——>SocketListener



二:Command注册

上面的CommandListener的构造函数中调用父类的注册函数register, 注册commad到FrameworkListener的mCommands容器中。

/system/core/libsysutils/src/FrameworkListener.cpp注册如下:

void FrameworkListener::registerCmd(FrameworkCommand *cmd) {    mCommands->push_back(cmd);}

可以看到这里的行参是FrameworkCommand 类型,

因为这几个command类的继承关系: VolumeCmd——>VoldCommand——>FrameworkCommand


我们这里以VolumeCmd 为例子学习:

CommandListener::VolumeCmd::VolumeCmd() :                 VoldCommand("volume") {}

VoldCommand::VoldCommand(const char *cmd) :              FrameworkCommand(cmd)  {}

FrameworkCommand::FrameworkCommand(const char *cmd) {    mCommand = cmd;}

将volume这个command注册到mCommands这个容器中之后,目的是当FrameworkListerer从SlocketListener接收到command的时候,

会依据mCommands 中的command进行解析筛选判断分发,调用对应的command执行类。



三:CommandListener运作

CommandListener所起到的作用,简单来说就是沟通Framwork和Vold,我画的一张简单的结构图,大体的运作如下:




开启CommandListener的监听cl->startListener()

CommandListener和FrameworkListener都没有重写这个方法,直接调用父类SocketListener的:

int SocketListener::startListener() {    if (!mSocketName && mSock == -1) {        SLOGE("Failed to start unbound listener");        errno = EINVAL;        return -1;    } else if (mSocketName) {        if ((mSock = android_get_control_socket(mSocketName)) < 0) {//获取socket的文件描述符,这里是获取Vold这个socket的            SLOGE("Obtaining file descriptor socket '%s' failed: %s",                 mSocketName, strerror(errno));            return -1;        }        SLOGV("got mSock = %d for %s", mSock, mSocketName);    }    if (mListen && listen(mSock, 4) < 0) {        SLOGE("Unable to listen on socket (%s)", strerror(errno));        return -1;    } else if (!mListen)//是否正常监听socket        mClients->push_back(new SocketClient(mSock, false, mUseCmdNum));    if (pipe(mCtrlPipe)) {//新建管道,保存文件描述符到数组        SLOGE("pipe failed (%s)", strerror(errno));        return -1;    }    if (pthread_create(&mThread, NULL, SocketListener::threadStart, this)) {//开了一个线程来处理        SLOGE("pthread_create (%s)", strerror(errno));        return -1;    }    return 0;}

往下新开了一个线程用于监听:

void *SocketListener::threadStart(void *obj) {    SocketListener *me = reinterpret_cast<SocketListener *>(obj);//threadStart为static函数,上面开线程创建的时候传了this,这里需要转换一个一样bit位的SocketListener指针    me->runListener();//SocketListener真正的执行函数    pthread_exit(NULL);    return NULL;}

下面就是对Socket的监听处理:

void SocketListener::runListener() {    SocketClientCollection *pendingList = new SocketClientCollection();//暂存mClients中的SocketClient    while(1) {        SocketClientCollection::iterator it;        fd_set read_fds;        int rc = 0;        int max = -1;        FD_ZERO(&read_fds);//清空文件描述符集read_fds         if (mListen) {            max = mSock;            FD_SET(mSock, &read_fds);//如果正常的监听,这里就把之前获得的vold的文件描述符添加进去        }        FD_SET(mCtrlPipe[0], &read_fds);//添加管道读取端的文件描述符        if (mCtrlPipe[0] > max)            max = mCtrlPipe[0];        pthread_mutex_lock(&mClientsLock);//加锁操作,多线程安全        for (it = mClients->begin(); it != mClients->end(); ++it) {//遍历mClients,获取fd 添加到read_fds            int fd = (*it)->getSocket();            FD_SET(fd, &read_fds);            if (fd > max)                max = fd;        }        pthread_mutex_unlock(&mClientsLock);//解锁        SLOGV("mListen=%d, max=%d, mSocketName=%s", mListen, max, mSocketName);//linux下socket编程的select,这里检测read_fds集合里面是否有可读的,也就是有没有数据过来,没有数据的文件描述符会从read_fds中被剔除,这里的select设置time out为NULL,阻塞操作,直到read_fds集合中描述符有变化        if ((rc = select(max + 1, &read_fds, NULL, NULL, NULL)) < 0) {            if (errno == EINTR)                continue;            SLOGE("select failed (%s) mListen=%d, max=%d", strerror(errno), mListen, max);            sleep(1);            continue;        } else if (!rc)            continue;        if (FD_ISSET(mCtrlPipe[0], &read_fds))//如果匿名管道有数据可读,就退出            break;        if (mListen && FD_ISSET(mSock, &read_fds)) {//如果是正常监听的 mListen 为true,然后mSock这个描述符有可读数据,就创建链接,新建异步处理的SocketClient加入到mClients容器,这里的mSock 是vold这个套接字的描述符            struct sockaddr addr;            socklen_t alen;            int c;            do {                alen = sizeof(addr);                c = accept(mSock, &addr, &alen);                SLOGV("%s got %d from accept", mSocketName, c);            } while (c < 0 && errno == EINTR);            if (c < 0) {                SLOGE("accept failed (%s)", strerror(errno));                sleep(1);                continue;            }            pthread_mutex_lock(&mClientsLock);            mClients->push_back(new SocketClient(c, true, mUseCmdNum));            pthread_mutex_unlock(&mClientsLock);        }        /* Add all active clients to the pending list first */        pendingList->clear();        pthread_mutex_lock(&mClientsLock);        for (it = mClients->begin(); it != mClients->end(); ++it) {//把上面有请求建立链接的Client加入到pendingList 容器中,后面处理            int fd = (*it)->getSocket();            if (FD_ISSET(fd, &read_fds)) {                pendingList->push_back(*it);            }        }        pthread_mutex_unlock(&mClientsLock);        /* Process the pending list, since it is owned by the thread,         * there is no need to lock it */        while (!pendingList->empty()) {//遍历处理            /* Pop the first item from the list */            it = pendingList->begin();            SocketClient* c = *it;            pendingList->erase(it);            /* Process it, if false is returned and our sockets are             * connection-based, remove and destroy it */            if (!onDataAvailable(c) && mListen) {//调用到FrameworkListener 中onDataAvailable处理Socket事件                /* Remove the client from our array */                SLOGV("going to zap %d for %s", c->getSocket(), mSocketName);                pthread_mutex_lock(&mClientsLock);                for (it = mClients->begin(); it != mClients->end(); ++it) {                    if (*it == c) {                        mClients->erase(it);//处理完成之后,从容器中移除这次的监听到的SocketClient                        break;                    }                }                pthread_mutex_unlock(&mClientsLock);                /* Remove our reference to the client */                c->decRef();            }        }    }    delete pendingList;}

这个函数是SocketListener的核心所在,真正的处理函数是onDataAvailable,这个是纯虚函数,/system/core/include/sysutils/SocketListener.h:

    virtual bool onDataAvailable(SocketClient *c) = 0;

在其子类 FrameworkListener.cpp中实现:

bool FrameworkListener::onDataAvailable(SocketClient *c) {    char buffer[255];    int len;    len = TEMP_FAILURE_RETRY(read(c->getSocket(), buffer, sizeof(buffer)));//读Socket 内容保存到buffer    if (len < 0) {        SLOGE("read() failed (%s)", strerror(errno));        return false;    } else if (!len)        return false;    int offset = 0;    int i;    for (i = 0; i < len; i++) {        if (buffer[i] == '\0') {//一次传入一个字符串            /* IMPORTANT: dispatchCommand() expects a zero-terminated string */            dispatchCommand(c, buffer + offset);            offset = i + 1;        }    }    return true;}

调用同类命令执行函数 dispatchCommand

void FrameworkListener::dispatchCommand(SocketClient *cli, char *data) {    FrameworkCommandCollection::iterator i;    int argc = 0;    char *argv[FrameworkListener::CMD_ARGS_MAX];    char tmp[255];...//解析判断command buffer    for (i = mCommands->begin(); i != mCommands->end(); ++i) {//遍历之前register到FrameworkListener中的FrameworkCommand容器        FrameworkCommand *c = *i;        if (!strcmp(argv[0], c->getCommand())) {//其中有注册“Volume”,如果这里是Volume开头的command,那么就调用,Volume构造的时候所构造的父类FrameworkCommand中的runCommand函数            if (c->runCommand(cli, argc, argv)) {                SLOGW("Handler '%s' error (%s)", c->getCommand(), strerror(errno));            }            goto out;        }    }}


同时/system/core/include/sysutils/FrameworkCommand.h:

    virtual int runCommand(SocketClient *c, int argc, char **argv) = 0;

实现在子类中,还是以Volume这个runcommand为例 /system/vold/CommandListener.cpp中:


int CommandListener::VolumeCmd::runCommand(SocketClient *cli,                                                      int argc, char **argv) {    dumpArgs(argc, argv, -1);    if (argc < 2) {        cli->sendMsg(ResponseCode::CommandSyntaxError, "Missing Argument", false);        return 0;    }    VolumeManager *vm = VolumeManager::Instance();//获取已经存在的VolumeManager实例...else if (!strcmp(argv[1], "mount")) {//判断command 内容        if (argc != 3) {            cli->sendMsg(ResponseCode::CommandSyntaxError, "Usage: volume mount <path>", false);            return 0;        }        rc = vm->mountVolume(argv[2]);//交给VolumeManager来对Volume进行操作    }...}


对CommandListener的分析就到这里,主要是怎么接收到的Socket,执行相对应的command,最后是怎么传递给VolumeManager,与上层MountService的交互后续分析,后续分析VolumeManager的初始化!





更多相关文章

  1. android 获得焦点(View get focus)
  2. android,NativeActivity使用
  3. Android(安卓)电源管理
  4. Android中的DownloadManager
  5. android 源码分析流程(一) init.c
  6. android实现开机自启动服务
  7. Android(安卓)GPS学习笔记—GpsLP初始化
  8. Android(安卓)NDK编程实现终端功能(调用system函数)
  9. 箭头函数的基础使用

随机推荐

  1. Android(安卓)- 开发者应该深入学习的10
  2. Android打包jar 和使用第三方库
  3. android map的使用方法
  4. Android开发知识概要
  5. Android(安卓)FrameLayout子view居中(左居
  6. Android核心功能
  7. Android的init过程(二):初始化语言(init.rc)解
  8. android之声音管理器AudioManager的使用
  9. Android之NDK开发
  10. 构建Android电话相关的应用