在Android系统,系统设置里面,
提供了挂载,卸载与格式化的功能。在这里,我们可以回忆一下,Android在挂载sd卡有几个途径,
卸载又是有几种方法?
一、挂载sd卡,有2种方式:
1.用户自己挂载sd卡;
2.自动挂载sd卡,这时候是在Android系统启动完成后挂载的,所以可以看成是自动挂载;
二、卸载sd卡,有2种方式:
1.用户自己卸载sd卡;
2.用户移除sd卡;
卸载sd卡,1和2看起来有点矛盾,但这相当于平时我们在电脑使用U盘一样,
一种是先安全删除再移除U盘;
一种是不安全删除直接移除U盘;
所以在Android系统中,卸载sd卡有两个途径:
1.Framework下发卸载命令(volume unmount sdcard force),卸载sd卡;
2.vold捕获到移除事件,如果是非安全删除sd卡,那么就卸载sd卡。
所以挂载与卸载sd卡的两种方法不同,挂载sd卡都是由Framework下发命令,而卸载sd卡则不同。
一、先来分析Framework下发卸载命令:
这条卸载命令的格式是:volume unmount sdcard true/false.
这里有一个强制卸载的标志,也就是force参数,如果命令包含“force”字符串,那么就强制
卸载sd卡,接下来看unmountVolume卸载函数:
开始看卸载函数,以下函数均做简化,不再贴出大量源码,Android系统的源码实在太多:
提供了挂载,卸载与格式化的功能。在这里,我们可以回忆一下,Android在挂载sd卡有几个途径,
卸载又是有几种方法?
一、挂载sd卡,有2种方式:
1.用户自己挂载sd卡;
2.自动挂载sd卡,这时候是在Android系统启动完成后挂载的,所以可以看成是自动挂载;
二、卸载sd卡,有2种方式:
1.用户自己卸载sd卡;
2.用户移除sd卡;
卸载sd卡,1和2看起来有点矛盾,但这相当于平时我们在电脑使用U盘一样,
一种是先安全删除再移除U盘;
一种是不安全删除直接移除U盘;
所以在Android系统中,卸载sd卡有两个途径:
1.Framework下发卸载命令(volume unmount sdcard force),卸载sd卡;
2.vold捕获到移除事件,如果是非安全删除sd卡,那么就卸载sd卡。
所以挂载与卸载sd卡的两种方法不同,挂载sd卡都是由Framework下发命令,而卸载sd卡则不同。
一、先来分析Framework下发卸载命令:
截取CommandListener类其中的源码:
- elseif(!strcmp(argv[1],"unmount")){
- if(argc<3||argc>4||(argc==4&&strcmp(argv[3],"force"))){
- cli->sendMsg(ResponseCode::CommandSyntaxError,"Usage:volumeunmount<path>[force]",false);
- return0;
- }
- boolforce=false;
- if(argc>=4&&!strcmp(argv[3],"force")){
- force=true;
- }
- rc=vm->unmountVolume(argv[2],force);
- }
这里有一个强制卸载的标志,也就是force参数,如果命令包含“force”字符串,那么就强制
卸载sd卡,接下来看unmountVolume卸载函数:
- intVolumeManager::unmountVolume(constchar*label,boolforce){
- Volume*v=lookupVolume(label);
- ......
- /*这函数清理了/mnt/asec目录的一些内容,其实看不见*/
- cleanupAsec(v,force);
- returnv->unmountVol(force);
- }
开始看卸载函数,以下函数均做简化,不再贴出大量源码,Android系统的源码实在太多:
- intVolume::unmountVol(boolforce){
- /*广播sd卡正在卸载的状态*/
- setState(Volume::State_Unmounting);
- if(doMoveMount(getMountpoint(),SEC_STGDIR,force)){
- SLOGE("Failedtomovemount%s=>%s(%s)",getMountpoint(),SEC_STGDIR,strerror(errno));
- setState(Volume::State_Mounted);
- return-1;
- }
- if(doUnmount(Volume::SEC_STG_SECIMGDIR,force)){
- SLOGE("Failedtounmounttmpfson%s(%s)",SEC_STG_SECIMGDIR,strerror(errno));
- gotofail_republish;
- }
- if(doUnmount(Volume::SEC_ASECDIR,force)){
- SLOGE("Failedtoremovebindmounton%s(%s)",SEC_ASECDIR,strerror(errno));
- gotofail_remount_tmpfs;
- }
- if(doUnmount(Volume::SEC_STGDIR,force)){
- SLOGE("Failedtounmount%s(%s)",SEC_STGDIR,strerror(errno));
- gotofail_recreate_bindmount;
- }
- /*以上doMoveMount,doUnmount等函数做些清理工作,就是之前挂载到系统的目录
- 清理干净*/
- /*卸载工作做完,告诉framework,该磁盘处于空闲状态*/
- setState(Volume::State_Idle);
- /*用来保存正在挂载的设备号的全局变量,现在赋为-1*/
- mCurrentlyMountedKdev=-1;
- return0;
- }
二、vold捕获移除事件,调用卸载函数:
- voidDirectVolume::handlePartitionRemoved(constchar*devpath,NetlinkEvent*evt){
- intmajor=atoi(evt->findParam("MAJOR"));
- intminor=atoi(evt->findParam("MINOR"));
- charmsg[255];
- intstate;
- SLOGD("Volume%s%spartition%d:%dremoved\n",getLabel(),getMountpoint(),major,minor);
- /*
- *Theframeworkdoesn'tneedtogetnotifiedof
- *partitionremovalunlessit'smounted.Otherwise
- *theremovalnotificationwillbesentontheDisk
- *itself
- */
- state=getState();
- if(state!=Volume::State_Mounted&&state!=Volume::State_Shared){
- return;
- }
- /*判断,如果移除事件的设备号与正在挂载系统的设备号相等,
- 说明此时是没有安全删除,所以下面会广播VolumeBadRemoval反馈码*/
- if((dev_t)MKDEV(major,minor)==mCurrentlyMountedKdev){
- /*
- *Yikes,ourmountedpartitionisgoingaway!
- */
- snprintf(msg,sizeof(msg),"Volume%s%sbadremoval(%d:%d)",
- getLabel(),getMountpoint(),major,minor);
- mVm->getBroadcaster()->sendBroadcast(ResponseCode::VolumeBadRemoval,
- msg,false);
- /*清理asec目录*/
- if(mVm->cleanupAsec(this,true)){
- SLOGE("FailedtocleanupASEC-unmountwillprobablyfail!");
- }
- /*在这里调用了卸载函数,跟framework下发命令卸载一样。*/
- if(Volume::unmountVol(true)){
- SLOGE("Failedtounmountvolumeonbadremoval(%s)",
- strerror(errno));
- //XXX:Atthispointwe'rescrewedfornow
- }else{
- SLOGD("Crisisaverted");
- }
- }elseif(state==Volume::State_Shared){
- /*这里的判断是,如果此时手机与电脑正在连接着使用时,移除事件的情况*/
- /*removedduringmassstorage*/
- snprintf(msg,sizeof(msg),"Volume%sbadremoval(%d:%d)",
- getLabel(),major,minor);
- mVm->getBroadcaster()->sendBroadcast(ResponseCode::VolumeBadRemoval,
- msg,false);
- /*卸载大容量存储*/
- if(mVm->unshareVolume(getLabel(),"ums")){
- SLOGE("Failedtounsharevolumeonbadremoval(%s)",
- strerror(errno));
- }else{
- SLOGD("Crisisaverted");
- }
- }
- }