Android SDCard UnMounted 流程分析(二)


上一篇講到通過NetlinkManager發送uevent 命令到NetlinkHandler 的onEvent,代碼如下:

void NetlinkHandler::onEvent(NetlinkEvent *evt) {
     VolumeManager *vm = VolumeManager::Instance();
     const  char *subsys = evt->getSubsystem();

     if (!subsys) {
        SLOGW( " No subsystem found in netlink event ");
         return;
    }
    SLOGD( " NetlinkHandler:OnEvent subsys values is %s ",subsys);
     if (!strcmp(subsys,  " block ")) {
        SLOGD( " NetlinkHandler:onEvent ");
         vm->handleBlockEvent(evt);
    }

 在NetlinkHandler 里面得一個VolumeManager,當收到的命令為block時調用VolumnManager的handleBlockEvent,如上加紅加粗的代碼。

handleBlockEvent實則是通過一個循環將事先將main事先讀取的配置文件:etc/vold.fstab存進VolumeCollection,得到VolumeCollection的對象,然后調用Volume 的handleBlockEvent,如代碼:

void VolumeManager::handleBlockEvent(NetlinkEvent *evt) {
     const  char *devpath = evt->findParam( " DEVPATH ");

     /*  Lookup a volume to handle this device  */
    VolumeCollection::iterator it;
     bool hit =  false;
     for (it = mVolumes->begin(); it != mVolumes->end(); ++it) {
         if (! (*it)->handleBlockEvent(evt)) {
#ifdef NETLINK_DEBUG
            SLOGD( " Device '%s' event handled by volume %s\n ", devpath, (*it)->getLabel());
#endif
            hit =  true;
             break;
        }
    }

     if (!hit) {
#ifdef NETLINK_DEBUG
        SLOGW( " No volumes handled block event for '%s' ", devpath);
#endif
    }

看一下Volume 的handleblockEvent代碼:

int Volume::handleBlockEvent(NetlinkEvent *evt) {
    errno = ENOSYS;
     return - 1;

 看起來好像沒做什么事,其實真的實現在於Volume 的子類,DirectVolume,DirectVolme 中重寫了handleBlockEvent,看代碼:

int DirectVolume::handleBlockEvent(NetlinkEvent *evt) {
     const  char *dp = evt->findParam( " DEVPATH ");

    PathCollection::iterator  it;
     for (it = mPaths->begin(); it != mPaths->end(); ++it) {
         if (!strncmp(dp, *it, strlen(*it))) {
             /*  We can handle this disk  */
             int action = evt->getAction();
             const  char *devtype = evt->findParam( " DEVTYPE ");

             if (action == NetlinkEvent::NlActionAdd) {
                 int major = atoi(evt->findParam( " MAJOR "));
                 int minor = atoi(evt->findParam( " MINOR "));
                 char nodepath[ 255];

                snprintf(nodepath,
                          sizeof(nodepath),  " /dev/block/vold/%d:%d ",
                         major, minor);
                 if (createDeviceNode(nodepath, major, minor)) {
                    SLOGE( " Error making device node '%s' (%s) ", nodepath,
                                                               strerror(errno));
                }
                 if (!strcmp(devtype,  " disk ")) {
                    handleDiskAdded(dp, evt);
                }  else {
                    handlePartitionAdded(dp, evt);
                }
            }  else  if (action == NetlinkEvent::NlActionRemove) {
                 if (!strcmp(devtype,  " disk ")) {
                     handleDiskRemoved(dp, evt);
                }  else {
                    SLOGD( " DirectVolume:handleBlockEvent--->handlePartitionRemoved ");
                     handlePartitionRemoved(dp, evt);
                }
            }  else  if (action == NetlinkEvent::NlActionChange) {
                 if (!strcmp(devtype,  " disk ")) {
                    handleDiskChanged(dp, evt);
                }  else {
                    handlePartitionChanged(dp, evt);
                }
            }  else {
                    SLOGW( " Ignoring non add/remove/change event ");
            }

             return  0;
        }
    }
    errno = ENODEV;
     return - 1;

 

因為我的板子還未完善,所以這里它認為我的sdcard是一個分區,但無關緊要,原理一樣,就根據分區的代碼跟蹤。:handlePartitionRemoved,由於代碼過多,只貼出核心代碼:

void DirectVolume::handlePartitionRemoved( const  char *devpath, NetlinkEvent *evt) {

  if ((dev_t) MKDEV(major, minor) == mCurrentlyMountedKdev) {
         /*
         * Yikes, our mounted partition is going away!
         
*/

        snprintf(msg,  sizeof(msg),  " Volume %s %s bad removal (%d:%d) ",
                 getLabel(), getMountpoint(), major, minor);
        SLOGD( " DirectVolume:(dev_t) MKDEV(major, minor) == mCurrentlyMountedKdev:%d,msg is :%s. ",mCurrentlyMountedKdev,msg);
         mVm->getBroadcaster()->sendBroadcast(ResponseCode::VolumeBadRemoval,
                                             msg, false);


     if (mVm->cleanupAsec( thistrue)) {
            SLOGE( " Failed to cleanup ASEC - unmount will probably fail! ");
        }

         if ( Volume::unmountVol(truefalse)) {
            SLOGE( " Failed to unmount volume on bad removal (%s) "
                 strerror(errno));
             //  XXX: At this point we're screwed for now
        }  else {
            SLOGD( " Crisis averted ");
        }
    }

 

 到此,直接調用父類的unmountVol方法,unmountVol會通過setState通知框架狀態改變。代碼太多,只推薦核心代碼:

int Volume::unmountVol( bool force,  bool revert) {
 setState(Volume::State_Unmounting);

 

 而setState會通過socket將msg消息傳給框架

mVm->getBroadcaster()->sendBroadcast(ResponseCode::VolumeStateChange,
                                         msg,  false); 

接下去的步驟是關於socket的操作,就不深入了。

小結

   到了這一步,Vold 向上層反饋的動作基本己經完成,下一篇文章將會講解Framework 如何取得Vold 反饋過來的數據。 



免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM