`

Android 2.3 SD卡挂载流程浅析(四)

 
阅读更多
前面的三篇博文《Android 2.3 SD卡挂载流程浅析(一)》、《Android 2.3 SD卡挂载流程浅析(二)》、《Android 2.3 SD卡挂载流程浅析(三)》的分析,知道了SD卡挂载的消息是如何从底层传递到上层的,在《Android 2.3 SD卡挂载流程浅析(三)》中,我们已经知道了最后是在updatePublicVolumeState()中调用onStorageStateChanged(),从而达到更新SD卡挂载信息的。在本文《Android 2.3 SD卡挂载流程浅析(四)》中,我会将前文提到的程序调用流程图画出来,并对代码进行简单的分析。

首先,还是挂出这张老图(因为每次都用这张图0_0...)。

就权当复习吧,这是SD卡的整个挂载流程,而程序的调用也是根据这个流程图来的。

1.接收并处理uevent

首先是接收因为插入SD卡被内核检测到而发出的Event;

NetlinkHandler::onEvent(NetlinkEvent *evt)

//代码路径:AndroidSourcecode2.3/system/vold/NetlinkHandler.cpp

//该方法主要通过evt->getSubsystem();方法来获取系统的event

view plain
  1. voidNetlinkHandler::onEvent(NetlinkEvent*evt){
  2. VolumeManager*vm=VolumeManager::Instance();
  3. constchar*subsys=evt->getSubsystem();
  4. if(!subsys){
  5. SLOGW("Nosubsystemfoundinnetlinkevent");
  6. return;
  7. }
  8. if(!strcmp(subsys,"block")){
  9. vm->handleBlockEvent(evt);
  10. }elseif(!strcmp(subsys,"switch")){
  11. vm->handleSwitchEvent(evt);
  12. }elseif(!strcmp(subsys,"usb_composite")){
  13. vm->handleUsbCompositeEvent(evt);
  14. }elseif(!strcmp(subsys,"battery")){
  15. }elseif(!strcmp(subsys,"power_supply")){
  16. }
  17. }
2.对SD卡挂载事件开始处理

void VolumeManager::handleBlockEvent(NetlinkEvent *evt)

//代码路径:AndroidSourcecode2.3/system/vold/VolumeManager.cpp

//该方法的主要作用是:
//第一, 遍历mPath容器,寻找与event对应的sysfs_path是否存在与mPath容器中。
//第二, 针对Event中的action有4种处理方式:Add,Removed,Change,Noaction。

view plain
  1. voidVolumeManager::handleBlockEvent(NetlinkEvent*evt){
  2. constchar*devpath=evt->findParam("DEVPATH");
  3. /*Lookupavolumetohandlethisdevice*/
  4. VolumeCollection::iteratorit;
  5. boolhit=false;
  6. for(it=mVolumes->begin();it!=mVolumes->end();++it){
  7. if(!(*it)->handleBlockEvent(evt)){
  8. #ifdefNETLINK_DEBUG
  9. SLOGD("Device'%s'eventhandledbyvolume%s\n",devpath,(*it)->getLabel());
  10. #endif
  11. hit=true;
  12. break;
  13. }
  14. }
  15. if(!hit){
  16. #ifdefNETLINK_DEBUG
  17. SLOGW("Novolumeshandledblockeventfor'%s'",devpath);
  18. #endif
  19. }
  20. }
3.对Block挂载事件进行处理

DirectVolume::handleBlockEvent(NetlinkEvent *evt)

//代码路径:AndroidSourcecode2.3/system/vold/DirectVolume.cpp

//在Add action中首先会创建设备节点,然后对disk和partion两种格式的设备分别进行处理。这里是disk格式。

view plain
  1. intDirectVolume::handleBlockEvent(NetlinkEvent*evt){
  2. constchar*dp=evt->findParam("DEVPATH");
  3. PathCollection::iteratorit;
  4. for(it=mPaths->begin();it!=mPaths->end();++it){
  5. if(!strncmp(dp,*it,strlen(*it))){
  6. /*Wecanhandlethisdisk*/
  7. intaction=evt->getAction();
  8. constchar*devtype=evt->findParam("DEVTYPE");
  9. if(action==NetlinkEvent::NlActionAdd){
  10. intmajor=atoi(evt->findParam("MAJOR"));
  11. intminor=atoi(evt->findParam("MINOR"));
  12. charnodepath[255];
  13. snprintf(nodepath,
  14. sizeof(nodepath),"/dev/block/vold/%d:%d",
  15. major,minor);
  16. if(createDeviceNode(nodepath,major,minor)){
  17. SLOGE("Errormakingdevicenode'%s'(%s)",nodepath,
  18. strerror(errno));
  19. }
  20. if(!strcmp(devtype,"disk")){
  21. <spanstyle="color:#ff0000;">handleDiskAdded(dp,evt);<spanstyle="color:#33cc00;">//SD卡插入是Add事件</span></span>
  22. }else{
  23. handlePartitionAdded(dp,evt);
  24. }
  25. }elseif(action==NetlinkEvent::NlActionRemove){
  26. if(!strcmp(devtype,"disk")){
  27. handleDiskRemoved(dp,evt);
  28. }else{
  29. handlePartitionRemoved(dp,evt);
  30. }
  31. }elseif(action==NetlinkEvent::NlActionChange){
  32. if(!strcmp(devtype,"disk")){
  33. handleDiskChanged(dp,evt);
  34. }else{
  35. handlePartitionChanged(dp,evt);
  36. }
  37. }else{
  38. SLOGW("Ignoringnonadd/remove/changeevent");
  39. }
  40. return0;
  41. }
  42. }
  43. errno=ENODEV;
  44. return-1;
  45. }
4.处理DiskAdd事件

DirectVolume::handleDiskAdded(const char *devpath, NetlinkEvent *evt)

//代码路径:AndroidSourcecode2.3/system/vold/DirectVolume.cpp

//在该方法中广播disk insert的广播消息(这里的广播不同于Java中的广播,这里实际上是Socket)。

view plain
  1. voidDirectVolume::handleDiskAdded(constchar*devpath,NetlinkEvent*evt){
  2. mDiskMajor=atoi(evt->findParam("MAJOR"));
  3. mDiskMinor=atoi(evt->findParam("MINOR"));
  4. constchar*tmp=evt->findParam("NPARTS");
  5. if(tmp){
  6. mDiskNumParts=atoi(tmp);
  7. }else{
  8. SLOGW("Kernelblockueventmissing'NPARTS'");
  9. mDiskNumParts=1;
  10. }
  11. charmsg[255];
  12. intpartmask=0;
  13. inti;
  14. for(i=1;i<=mDiskNumParts;i++){
  15. partmask|=(1<<i);
  16. }
  17. mPendingPartMap=partmask;
  18. if(mDiskNumParts==0){
  19. #ifdefPARTITION_DEBUG
  20. SLOGD("Dv::diskIns-Nopartitions-goodtogoson!");
  21. #endif
  22. setState(Volume::State_Idle);
  23. }else{
  24. #ifdefPARTITION_DEBUG
  25. SLOGD("Dv::diskIns-waitingfor%dpartitions(mask0x%x)",
  26. mDiskNumParts,mPendingPartMap);
  27. #endif
  28. setState(Volume::State_Pending);
  29. }
  30. snprintf(msg,sizeof(msg),"Volume%s%sdiskinserted(%d:%d)",
  31. getLabel(),getMountpoint(),mDiskMajor,mDiskMinor);
  32. mVm->getBroadcaster()->sendBroadcast(ResponseCode::VolumeDiskInserted,
  33. msg,false);


5.处理广播消息
SocketListener::runListener()

//代码路径:AndroidSourcecode2.3/system/core/libsysutils/src/SocketListener.cpp

//完成对Socket的监听以及对数据的处理onDataAvailable(* it );

view plain
  1. voidSocketListener::runListener(){
  2. while(1){
  3. SocketClientCollection::iteratorit;
  4. fd_setread_fds;
  5. intrc=0;
  6. intmax=0;
  7. FD_ZERO(&read_fds);
  8. if(mListen){
  9. max=mSock;
  10. FD_SET(mSock,&read_fds);
  11. }
  12. FD_SET(mCtrlPipe[0],&read_fds);
  13. if(mCtrlPipe[0]>max)
  14. max=mCtrlPipe[0];
  15. pthread_mutex_lock(&mClientsLock);
  16. for(it=mClients->begin();it!=mClients->end();++it){
  17. FD_SET((*it)->getSocket(),&read_fds);
  18. if((*it)->getSocket()>max)
  19. max=(*it)->getSocket();
  20. }
  21. pthread_mutex_unlock(&mClientsLock);
  22. if((rc=select(max+1,&read_fds,NULL,NULL,NULL))<0){
  23. SLOGE("selectfailed(%s)",strerror(errno));
  24. sleep(1);
  25. continue;
  26. }elseif(!rc)
  27. continue;
  28. if(FD_ISSET(mCtrlPipe[0],&read_fds))
  29. break;
  30. if(mListen&&FD_ISSET(mSock,&read_fds)){
  31. structsockaddraddr;
  32. socklen_talen=sizeof(addr);
  33. intc;
  34. if((c=accept(mSock,&addr,&alen))<0){
  35. SLOGE("acceptfailed(%s)",strerror(errno));
  36. sleep(1);
  37. continue;
  38. }
  39. pthread_mutex_lock(&mClientsLock);
  40. mClients->push_back(newSocketClient(c));
  41. pthread_mutex_unlock(&mClientsLock);
  42. }
  43. do{
  44. pthread_mutex_lock(&mClientsLock);
  45. for(it=mClients->begin();it!=mClients->end();++it){
  46. intfd=(*it)->getSocket();
  47. if(FD_ISSET(fd,&read_fds)){
  48. pthread_mutex_unlock(&mClientsLock);
  49. if(!<spanstyle="color:#ff0000;">onDataAvailable(*it)</span>){
  50. close(fd);
  51. pthread_mutex_lock(&mClientsLock);
  52. delete*it;
  53. it=mClients->erase(it);
  54. pthread_mutex_unlock(&mClientsLock);
  55. }
  56. FD_CLR(fd,&read_fds);
  57. pthread_mutex_lock(&mClientsLock);
  58. continue;
  59. }
  60. }
  61. pthread_mutex_unlock(&mClientsLock);
  62. }while(0);
  63. }
  64. }

6.处理消息内容

FrameworkListener::onDataAvailable(SocketClient *c)

//代码路径:AndroidSourcecode2.3/system/core/libsysutils/src/FrameworkListener.cpp

//对接收到的广播消息进行处理

view plain
  1. boolFrameworkListener::onDataAvailable(SocketClient*c){
  2. charbuffer[255];
  3. intlen;
  4. if((len=read(c->getSocket(),buffer,sizeof(buffer)-1))<0){
  5. SLOGE("read()failed(%s)",strerror(errno));
  6. returnfalse;
  7. }elseif(!len)
  8. returnfalse;
  9. intoffset=0;
  10. inti;
  11. for(i=0;i<len;i++){
  12. if(buffer[i]=='\0'){
  13. dispatchCommand(c,buffer+offset);
  14. offset=i+1;
  15. }
  16. }
  17. returntrue;
  18. }
7.分发指令

FrameworkListener::dispatchCommand(SocketClient *cli, char *data)

//代码路径:AndroidSourcecode2.3/system/core/libsysutils/src/FrameworkListener.cpp

//分配指令:DumpCmd、VolumeCmd、AsecCmd、ShareCmd、StorageCmd、XwarpCmd

view plain
  1. voidFrameworkListener::dispatchCommand(SocketClient*cli,char*data){
  2. FrameworkCommandCollection::iteratori;
  3. intargc=0;
  4. char*argv[FrameworkListener::CMD_ARGS_MAX];
  5. chartmp[255];
  6. char*p=data;
  7. char*q=tmp;
  8. boolesc=false;
  9. boolquote=false;
  10. intk;
  11. memset(argv,0,sizeof(argv));
  12. memset(tmp,0,sizeof(tmp));
  13. while(*p){
  14. if(*p=='\\'){
  15. if(esc){
  16. *q++='\\';
  17. esc=false;
  18. }else
  19. esc=true;
  20. p++;
  21. continue;
  22. }elseif(esc){
  23. if(*p=='"')
  24. *q++='"';
  25. elseif(*p=='\\')
  26. *q++='\\';
  27. else{
  28. cli->sendMsg(500,"Unsupportedescapesequence",false);
  29. gotoout;
  30. }
  31. p++;
  32. esc=false;
  33. continue;
  34. }
  35. if(*p=='"'){
  36. if(quote)
  37. quote=false;
  38. else
  39. quote=true;
  40. p++;
  41. continue;
  42. }
  43. *q=*p++;
  44. if(!quote&&*q==''){
  45. *q='\0';
  46. argv[argc++]=strdup(tmp);
  47. memset(tmp,0,sizeof(tmp));
  48. q=tmp;
  49. continue;
  50. }
  51. q++;
  52. }
  53. argv[argc++]=strdup(tmp);
  54. #if0
  55. for(k=0;k<argc;k++){
  56. SLOGD("arg[%d]='%s'",k,argv[k]);
  57. }
  58. #endif
  59. if(quote){
  60. cli->sendMsg(500,"Unclosedquoteserror",false);
  61. gotoout;
  62. }
  63. for(i=mCommands->begin();i!=mCommands->end();++i){
  64. FrameworkCommand*c=*i;
  65. if(!strcmp(argv[0],c->getCommand())){
  66. if(c-><spanstyle="color:#ff0000;">runCommand</span>(cli,argc,argv)){
  67. SLOGW("Handler'%s'error(%s)",c->getCommand(),strerror(errno));
  68. }
  69. gotoout;
  70. }
  71. }
  72. cli->sendMsg(500,"Commandnotrecognized",false);
  73. out:
  74. intj;
  75. for(j=0;j<argc;j++)
  76. free(argv[j]);
  77. return;
  78. }
8.开始执行挂载

CommandListener::VolumeCmd::runCommand(SocketClient *cli,int argc, char **argv)

//代码路径:AndroidSourcecode2.3/system/vold/CommandListener.cpp

//rc = vm->mountVolume(argv[2]);

view plain
  1. intCommandListener::VolumeCmd::runCommand(SocketClient*cli,intargc,char**argv){
  2. dumpArgs(argc,argv,-1);
  3. if(argc<2){
  4. cli->sendMsg(ResponseCode::CommandSyntaxError,"MissingArgument",false);
  5. return0;
  6. }
  7. VolumeManager*vm=VolumeManager::Instance();
  8. intrc=0;
  9. if(!strcmp(argv[1],"list")){
  10. returnvm->listVolumes(cli);
  11. }elseif(!strcmp(argv[1],"debug")){
  12. if(argc!=3||(argc==3&&(strcmp(argv[2],"off")&&strcmp(argv[2],"on")))){
  13. cli->sendMsg(ResponseCode::CommandSyntaxError,"Usage:volumedebug<off/on>",false);
  14. return0;
  15. }
  16. vm->setDebug(!strcmp(argv[2],"on")?true:false);
  17. }elseif(!strcmp(argv[1],"mount")){
  18. if(argc!=3){
  19. cli->sendMsg(ResponseCode::CommandSyntaxError,"Usage:volumemount<path>",false);
  20. return0;
  21. }
  22. <spanstyle="color:#ff0000;">rc=vm->mountVolume(argv[2]);</span>
  23. }elseif(!strcmp(argv[1],"unmount")){
  24. if(argc<3||argc>4||(argc==4&&strcmp(argv[3],"force"))){
  25. cli->sendMsg(ResponseCode::CommandSyntaxError,"Usage:volumeunmount<path>[force]",false);
  26. return0;
  27. }
  28. boolforce=false;
  29. if(argc>=4&&!strcmp(argv[3],"force")){
  30. force=true;
  31. }
  32. rc=vm->unmountVolume(argv[2],force);
  33. }elseif(!strcmp(argv[1],"format")){
  34. if(argc!=3){
  35. cli->sendMsg(ResponseCode::CommandSyntaxError,"Usage:volumeformat<path>",false);
  36. return0;
  37. }
  38. rc=vm->formatVolume(argv[2]);
  39. }elseif(!strcmp(argv[1],"share")){
  40. if(argc!=4){
  41. cli->sendMsg(ResponseCode::CommandSyntaxError,
  42. "Usage:volumeshare<path><method>",false);
  43. return0;
  44. }
  45. rc=vm->shareVolume(argv[2],argv[3]);
  46. }elseif(!strcmp(argv[1],"unshare")){
  47. if(argc!=4){
  48. cli->sendMsg(ResponseCode::CommandSyntaxError,
  49. "Usage:volumeunshare<path><method>",false);
  50. return0;
  51. }
  52. rc=vm->unshareVolume(argv[2],argv[3]);
  53. }elseif(!strcmp(argv[1],"shared")){
  54. boolenabled=false;
  55. if(argc!=4){
  56. cli->sendMsg(ResponseCode::CommandSyntaxError,
  57. "Usage:volumeshared<path><method>",false);
  58. return0;
  59. }
  60. if(vm->shareEnabled(argv[2],argv[3],&enabled)){
  61. cli->sendMsg(
  62. ResponseCode::OperationFailed,"Failedtodetermineshareenablestate",true);
  63. }else{
  64. cli->sendMsg(ResponseCode::ShareEnabledResult,
  65. (enabled?"Shareenabled":"Sharedisabled"),false);
  66. }
  67. return0;
  68. }else{
  69. cli->sendMsg(ResponseCode::CommandSyntaxError,"Unknownvolumecmd",false);
  70. }
  71. if(!rc){
  72. cli->sendMsg(ResponseCode::CommandOkay,"volumeoperationsucceeded",false);
  73. }else{
  74. interno=errno;
  75. rc=ResponseCode::convertFromErrno();
  76. cli->sendMsg(rc,"volumeoperationfailed",true);
  77. }
  78. return0;
  79. }

9.调用方法执行挂载动作

VolumeManager::mountVolume(const char *label)

//代码路径:AndroidSourcecode2.3/system/vold/VolumeManager.cpp
//v->mountVol();

view plain
  1. intVolumeManager::mountVolume(constchar*label){
  2. Volume*v=lookupVolume(label);
  3. if(!v){
  4. errno=ENOENT;
  5. return-1;
  6. }
  7. return<spanstyle="color:#ff0000;">v->mountVol();
  8. </span>}
view plain
  1. intVolumeManager::mountVolume(constchar*label){
  2. Volume*v=lookupVolume(label);
  3. if(!v){
  4. errno=ENOENT;
  5. return-1;
  6. }
  7. return<spanstyle="color:#ff0000;">v->mountVol();
  8. </span>}
10.真正的挂载者

Volume::mountVol()

//代码路径:AndroidSourcecode2.3/system/vold/Volume.cpp

//SD卡的挂载最终是在该方法中实现的,如果挂载有异常,也会在该方法的执行过程通过setState方法发出广播。

view plain
  1. intVolume::mountVol(){
  2. dev_tdeviceNodes[4];
  3. intn,i,rc=0;
  4. charerrmsg[255];
  5. if(getState()==Volume::State_NoMedia){
  6. snprintf(errmsg,sizeof(errmsg),
  7. "Volume%s%smountfailed-nomedia",
  8. getLabel(),getMountpoint());
  9. mVm->getBroadcaster()->sendBroadcast(
  10. ResponseCode::VolumeMountFailedNoMedia,
  11. errmsg,false);
  12. errno=ENODEV;
  13. return-1;
  14. }elseif(getState()!=Volume::State_Idle){
  15. errno=EBUSY;
  16. return-1;
  17. }
  18. if(isMountpointMounted(getMountpoint())){
  19. SLOGW("Volumeisidlebutappearstobemounted-fixing");
  20. setState(Volume::State_Mounted);
  21. //mCurrentlyMountedKdev=XXX
  22. return0;
  23. }
  24. n=getDeviceNodes((dev_t*)&deviceNodes,4);
  25. if(!n){
  26. SLOGE("Failedtogetdevicenodes(%s)\n",strerror(errno));
  27. return-1;
  28. }
  29. for(i=0;i<n;i++){
  30. chardevicePath[255];
  31. sprintf(devicePath,"/dev/block/vold/%d:%d",MAJOR(deviceNodes[i]),
  32. MINOR(deviceNodes[i]));
  33. SLOGI("%sbeingconsideredforvolume%s\n",devicePath,getLabel());
  34. errno=0;
  35. setState(Volume::State_Checking);
  36. if(Fat::check(devicePath)){//如果SD卡的格式不对是通不过这里的检测的
  37. if(errno==ENODATA){
  38. SLOGW("%sdoesnotcontainaFATfilesystem\n",devicePath);
  39. continue;
  40. }
  41. errno=EIO;
  42. /*Badness-abortthemount*/
  43. SLOGE("%sfailedFSchecks(%s)",devicePath,strerror(errno));
  44. setState(Volume::State_Idle);
  45. return-1;
  46. }
  47. /*
  48. *Mountthedeviceonourinternalstagingmountpointsowecan
  49. *muckwithitbeforeexposingittononpriviledgedusers.
  50. */
  51. errno=0;
  52. if(Fat::doMount(devicePath,"/mnt/secure/staging",false,false,false,
  53. 1000,1015,0702,true)){//真正的挂载方法doMount
  54. SLOGE("%sfailedtomountviaVFAT(%s)\n",devicePath,strerror(errno));
  55. continue;
  56. }
  57. SLOGI("Device%s,target%smounted@/mnt/secure/staging",devicePath,getMountpoint());
  58. protectFromAutorunStupidity();
  59. if(createBindMounts()){
  60. SLOGE("Failedtocreatebindmounts(%s)",strerror(errno));
  61. umount("/mnt/secure/staging");
  62. setState(Volume::State_Idle);
  63. return-1;
  64. }
  65. /*
  66. *Nowthatthebindmounttrickeryisdone,atomicallymovethe
  67. *wholesubtreetoexposeittononpriviledgedusers.
  68. */
  69. if(doMoveMount("/mnt/secure/staging",getMountpoint(),false)){
  70. SLOGE("Failedtomovemount(%s)",strerror(errno));
  71. umount("/mnt/secure/staging");
  72. setState(Volume::State_Idle);
  73. return-1;
  74. }
  75. setState(Volume::State_Mounted);
  76. mCurrentlyMountedKdev=deviceNodes[i];
  77. return0;
  78. }
  79. SLOGE("Volume%sfoundnosuitabledevicesformounting:(\n",getLabel());
  80. setState(Volume::State_Idle);
  81. return-1;
  82. }

到这里SD卡的挂载基本上已经完成,但是我们的目的是理清一条从底向上的路线,因此我会继续向上分析。我会将这一点在下一篇博文《Android 2.3 SD卡挂载流程浅析(五)》中继续分析。 因为这些都是我个人的一些见解,因此不见得都正确,希望读者抱着怀疑的态度阅读。不过不是有句名言叫“大胆假设,小心求证”吗!如文中有错误,还恳请各位看官指正。
分享到:
评论

相关推荐

Global site tag (gtag.js) - Google Analytics