博客
关于我
强烈建议你试试无所不能的chatGPT,快点击我
Android SDCard UnMounted 流程分析(二)
阅读量:5823 次
发布时间:2019-06-18

本文共 4035 字,大约阅读时间需要 13 分钟。

 上一篇讲到通过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(
this
true)) {

            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 反馈过来的数据。 

 

 
 本文转自 terry_龙 51CTO博客,原文链接:http://blog.51cto.com/terryblog/814963
,如需转载请自行联系原作者
你可能感兴趣的文章
使用《Deep Image Prior》来做图像复原
查看>>
Linux基础命令---rmdir
查看>>
Android图片添加水印图片并把图片保存到文件存储
查看>>
BigDecimal 舍入模式(Rounding mode)介绍
查看>>
开源 免费 java CMS - FreeCMS1.2-标签 infoSign
查看>>
开源 免费 java CMS - FreeCMS1.9 移动APP生成栏目列表数据
查看>>
Squid 反向代理服务器配置
查看>>
Java I/O操作
查看>>
Tomcat性能调优
查看>>
Android自学--一篇文章基本掌握所有的常用View组件
查看>>
灰度图像和彩色图像
查看>>
TCP segmentation offload
查看>>
FreeMarker-Built-ins for strings
查看>>
argparse - 命令行选项与参数解析(转)
查看>>
修改上一篇文章的node.js代码,支持默认页及支持中文
查看>>
Php实现版本比较接口
查看>>
删除设备和驱动器中软件图标
查看>>
第四章 TCP粘包/拆包问题的解决之道---4.1---
查看>>
html语言
查看>>
从源码看集合ArrayList
查看>>