上一篇讲到通过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 反馈过来的数据。

更多相关文章

  1. Android实现用代码简单安装和卸载APK的方法
  2. Android调用系统, 任意比例裁剪图片
  3. Android(安卓)屏幕适配之框架(AndroidAutoSize)(今日头条)适配
  4. AndroidStudio中的gradle脚本文件解读
  5. android启动界面
  6. Android中对同一个TextView设置不同字体样式
  7. Android学习之路七:DatePicker和TimePicker
  8. Android(安卓)开发绕不过的坑:你的 Bitmap 究竟占多大内存?
  9. Android(安卓)APP启动过程中应用代码的加载

随机推荐

  1. SQL on Hadoop 技术分析(二)
  2. Yarn【label-based scheduling】实战总结
  3. Yarn【label-based scheduling】实战总结
  4. BAT大佬带你了解AB测试
  5. Vue3 系统入门与项目实战
  6. 端午搬砖:聊聊调度云服务
  7. 原创 | 后疫情时代下5G安全的风险防控及
  8. 原创 | 工业网络通讯数据分析之Wireshark
  9. 闲聊乐视
  10. Cosmos DB的5种事物一致性