Android(安卓)SDCard UnMounted 流程分析(二)
16lz
2021-01-24
上一篇讲到通过NetlinkManager发送uevent 命令到NetlinkHandler 的onEvent,代码如下:
voidNetlinkHandler::onEvent(NetlinkEvent*evt){VolumeManager*vm=VolumeManager::Instance();
const char*subsys=evt->getSubsystem();
if(!subsys){
SLOGW( " Nosubsystemfoundinnetlinkevent ");
return;
}
SLOGD( " NetlinkHandler:OnEventsubsysvaluesis%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,如代码:
voidVolumeManager::handleBlockEvent(NetlinkEvent*evt){const char*devpath=evt->findParam( " DEVPATH ");
/* Lookupavolumetohandlethisdevice */
VolumeCollection::iteratorit;
boolhit= false;
for(it=mVolumes->begin();it!=mVolumes->end();++it){
if(! (*it)->handleBlockEvent(evt)){
#ifdefNETLINK_DEBUG
SLOGD( " Device'%s'eventhandledbyvolume%s\n ",devpath,(*it)->getLabel());
#endif
hit= true;
break;
}
}
if(!hit){
#ifdefNETLINK_DEBUG
SLOGW( " Novolumeshandledblockeventfor'%s' ",devpath);
#endif
} 复制代码
看一下Volume 的handleblockEvent代码:
intVolume::handleBlockEvent(NetlinkEvent*evt){errno=ENOSYS;
return- 1; 复制代码
看起来好像没做什么事,其实真的实现在于Volume 的子类,DirectVolume,DirectVolme 中重写了handleBlockEvent,看代码:
intDirectVolume::handleBlockEvent(NetlinkEvent*evt){const char*dp=evt->findParam( " DEVPATH ");
PathCollection::iteratorit;
for(it=mPaths->begin();it!=mPaths->end();++it){
if(!strncmp(dp,*it,strlen(*it))){
/* Wecanhandlethisdisk */
intaction=evt->getAction();
const char*devtype=evt->findParam( " DEVTYPE ");
if(action==NetlinkEvent::NlActionAdd){
intmajor=atoi(evt->findParam( " MAJOR "));
intminor=atoi(evt->findParam( " MINOR "));
charnodepath[ 255];
snprintf(nodepath,
sizeof(nodepath), " /dev/block/vold/%d:%d ",
major,minor);
if(createDeviceNode(nodepath,major,minor)){
SLOGE( " Errormakingdevicenode'%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( " Ignoringnonadd/remove/changeevent ");
}
return 0;
}
}
errno=ENODEV;
return- 1;
} 复制代码
因为我的板子还未完善,所以这里它认为我的sdcard是一个分区,但无关紧要,原理一样,就根据分区的代码跟踪。:handlePartitionRemoved,由于代码过多,只贴出核心代码:
voidDirectVolume::handlePartitionRemoved( const char*devpath,NetlinkEvent*evt){if((dev_t)MKDEV(major,minor)==mCurrentlyMountedKdev){
/*
*Yikes,ourmountedpartitionisgoingaway!
*/
snprintf(msg, sizeof(msg), " Volume%s%sbadremoval(%d:%d) ",
getLabel(),getMountpoint(),major,minor);
SLOGD( " DirectVolume:(dev_t)MKDEV(major,minor)==mCurrentlyMountedKdev:%d,msgis:%s. ",mCurrentlyMountedKdev,msg);
mVm->getBroadcaster()->sendBroadcast(ResponseCode::VolumeBadRemoval,
msg,false);
if(mVm->cleanupAsec( this, true)){
SLOGE( " FailedtocleanupASEC-unmountwillprobablyfail! ");
}
if( Volume::unmountVol(true,false)){
SLOGE( " Failedtounmountvolumeonbadremoval(%s) ",
strerror(errno));
// XXX:Atthispointwe'rescrewedfornow
} else{
SLOGD( " Crisisaverted ");
}
}
} 复制代码
到此,直接调用父类的unmountVol方法,unmountVol会通过setState通知框架状态改变。代码太多,只推荐核心代码:
intVolume::unmountVol( boolforce, boolrevert){setState(Volume::State_Unmounting);
} 复制代码
而setState会通过socket将msg消息传给框架
mVm->getBroadcaster()->sendBroadcast(ResponseCode::VolumeStateChange,msg, false); 复制代码
接下去的步骤是关于socket的操作,就不深入了。
小结
到了这一步,Vold 向上层反馈的动作基本己经完成,下一篇文章将会讲解Framework 如何取得Vold 反馈过来的数据。
更多相关文章
- Android实现用代码简单安装和卸载APK的方法
- Android调用系统, 任意比例裁剪图片
- Android(安卓)屏幕适配之框架(AndroidAutoSize)(今日头条)适配
- AndroidStudio中的gradle脚本文件解读
- android启动界面
- Android中对同一个TextView设置不同字体样式
- Android学习之路七:DatePicker和TimePicker
- Android(安卓)开发绕不过的坑:你的 Bitmap 究竟占多大内存?
- Android(安卓)APP启动过程中应用代码的加载