回顾:前帖分析了Vold的main()函数和NetlinkManager的函数调用流程,截止到NetlinkHandler的创建和start()调用,本帖继续分析源码
  1、处理block类型的uevent
  main()函数创建了CommandListener对象,NetlinkManager的start()函数又创建了NetlinkHandler对象,如果将CommandListener类和NetlinkHandler类的继承关系图画出来,会发现它们都是从SocketListener类派生出来的,如下图所示:

图1 NetlinkHandler和CommandListener的继承关系
  原理:处于最底层的SocketListener类的作用是监听socket的数据,接收到数据后分别交给FrameworkListener类和NetlinkListener类的函数,并分别对来自Framework和驱动的数据进行分析,分析后根据命令再分别调用CommandListener和NetlinkHandler中的函数。
  观察NetlinkHandler类的构造方法,代码如下:
Java代码
    - NetlinkHandler::NetlinkHandler(int listenerSocket) :  
-                 NetlinkListener(listenerSocket) {  
- }  
  这个构造方法很简单,再看看它的start()方法,代码如下:
Java代码
    - int NetlinkHandler::start() {  
-     return this->startListener();  
- }  
  可以发现,start()方法调用了SocketListener的startListener()函数,代码如下:
Java代码
    - int SocketListener::startListener(int backlog) {  
-      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) {  
-                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, backlog) < 0) {  
-          SLOGE("Unable to listen on socket (%s)", strerror(errno));  
-          return -1;  
-      } else if (!mListen)  
-           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;  
- }  
  startListener()函数开始监听socket,这个函数在NetlinkHandler中会被调用,在CommandListener也会被调用。
  startListener()函数首先判断变量mSocketName是否有值,只有CommandListener对象会对这个变量赋值,它的值就是在init.rc中定义的socket字符串。
  调用函数 android_get_control_socket()的目的是从环境变量中取得socket的值,这样CommandListener对象得到了它需要监听的socket,
  而对于NetlinkHandler对象而言,它的mSocket不为NULL,前面已经创建了socket。
  startListener()函数接下来会根据成员变量mListener的值来判断是否需要调用Listen()函数来监听socket。这个mListen的值在对象构造时根据参数来初始化。
  对于CommandListener对象,mListener的值为ture,对于NetlinkHandler对象,mListener的值为false,这是因为CommandListener对象和SystemServer通信,需要监听socket连接,而NetlinkHandler对象则不用。
  接下来startListener()函数会创建一个管道,这个管道的作用是通知线程停止监听,这个线程就是startListener()函数最后创建的监听线程,它的运行函数是threadStart(),在前贴的NetlinkManager家族图系中我们可以清晰的发现,其代码如下:
Java代码
    - void *SocketListener::threadStart(void *obj) {  
-      SocketListener *me = reinterpret_cast<SocketListener *>(obj);  
-      me->runListener();                                               
-      pthread_exit(NULL);  
-      return NULL;  
- }  
  threadStart()中又调用了runListener()函数,代码如下:
Java代码
    - void SocketListener::runListener() {  
-   
-       SocketClientCollection pendingList;  
-   
-       while(1) {               
-             SocketClientCollection::iterator it;  
-             fd_set read_fds;  
-             int rc = 0;  
-             int max = -1;  
-   
-             FD_ZERO(&read_fds);         
-   
-             if (mListen) {              
-                 max = mSock;  
-                 FD_SET(mSock, &read_fds);                 
-             }  
-   
-             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) {      
-                   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);  
-             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)) {  
-                 char c = CtrlPipe_Shutdown;  
-                 TEMP_FAILURE_RETRY(read(mCtrlPipe[0], &c, 1));  
-                 if (c == CtrlPipe_Shutdown) {  
-                     break;  
-                 }  
-                 continue;  
-             }  
-             if (mListen && FD_ISSET(mSock, &read_fds)) {             
-                 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);  
-             }  
-               
-               
-             pendingList.clear();  
-             pthread_mutex_lock(&mClientsLock);  
-             for (it = mClients->begin(); it != mClients->end(); ++it) {  
-                  SocketClient* c = *it;  
-                  int fd = c->getSocket();  
-                  if (FD_ISSET(fd, &read_fds)) {  
-                      pendingList.push_back(c);               
-                      c->incRef();  
-                  }  
-             }  
-             pthread_mutex_unlock(&mClientsLock);  
-   
-               
-             while (!pendingList.empty()) {                   
-                     
-                   it = pendingList.begin();  
-                   SocketClient* c = *it;  
-                   pendingList.erase(it);                     
-                     
-                   if (!onDataAvailable(c)) {  
-                       release(c, false);     
-                   }  
-                   c->decRef();  
-             }  
-       }  
- }  
  SocketListener::runListener是线程真正执行的函数。
  以上runListener()函数虽然比较长,但这是一段标准的处理混合socket连接的代码,对于我们编写socket的程序大有帮助,这里先做简单了解。
  <--------接下来,我们继续分析......-------->
  runListener()函数收到从驱动传递的数据或者MountService传递的数据后,调用onDataAvailable()函数来处理,FrameworkListener类和NetlinkListener类都会重载这个函数。
  首先来分析一下NetlinkListener类的onDataAvailable()函数是如何实现的!
  直接上代码:
Java代码
    - bool NetlinkListener::onDataAvailable(SocketClient *cli)  
- {  
-       int socket = cli->getSocket();  
-       ssize_t count;  
-       uid_t uid = -1;  
-         
-       count = TEMP_FAILURE_RETRY(uevent_kernel_multicast_uid_recv(socket, mBuffer, sizeof(mBuffer), &uid));  
-       if (count < 0) {                       
-           if (uid > 0)  
-               LOG_EVENT_INT(65537, uid);  
-           return false;  
-       }  
-   
-       NetlinkEvent *evt = new NetlinkEvent();       
-       if (evt->decode(mBuffer, count, mFormat)) {       
-           onEvent(evt);                             
-           SLOGE("Error decoding NetlinkEvent");  
-       }  
-       delete evt;  
-       return true;  
- }  
  NetlinkListener类的onDataAvailable()函数首先调用uevent_kernel_multicast_uid_recv()函数来接收uevent消息。
  接收到消息后,会创建NetlinkEvent对象,然后调用它的decode()函数对消息进行解码,然后用得到的消息数据给NetlinkEvent对象的成员变量赋值。
  最后onDataAvailable()函数调用了onEvent()函数继续处理消息,onEvent()函数的代码如下:
Java代码
    - void NetlinkHandler::onEvent(NetlinkEvent *evt) {  
-       VolumeManager *vm = VolumeManager::Instance();  
-       const char *subsys = evt->getSubsystem();  
-   
-       if (!subsys) {  
-           SLOGW("No subsystem found in netlink event");  
-           return;  
-       }  
-   
-       if (!strcmp(subsys, "block")) {  
-           vm->handleBlockEvent(evt);             
-       }  
- }  
  NetlinkHandler的onEvent()函数中会判断event属于哪个子系统的,如果属于“block”(SD热插拔),则调用VolumeManager的handleBlockEvent()函数来处理,代码如下:
Java代码
    - void VolumeManager::handleBlockEvent(NetlinkEvent *evt) {  
-       const char *devpath = evt->findParam("DEVPATH");  
-       VolumeCollection::iterator it;  
-       bool hit = false;  
-       for (it = mVolumes->begin(); it != mVolumes->end(); ++it) {  
-            if (!(*it)->handleBlockEvent(evt)) {          
-                hit = true;                               
-                break;  
-            }  
-       }  
- .....  
- }  
  总结:本帖的源码分析先到这里为止,下一贴再分析DirectVolume对象的handleBlockEvent()函数以及CommandListener对象如何处理从MountService发送的命令数据,即我们之前还没有讨论的关于FrameworkListener的onDataAvailable()函数的代码!