Android4.4----Vold挂载管理分析USB挂载(三)

来源:互联网 发布:app下载软件 编辑:程序博客网 时间:2024/06/12 01:24

        在上一篇Android4.4----Vold挂载管理分析USB挂载(二)中分析了Vold如何接收kernel的uevent并传递到VolumeManager的过程,这里继上篇文章继续分析VolumeManager接收到uevent事件后的处理过程!

         那我们先分析一下VolumeManager!

一:VolumeManager

       VolumeManager就是整个Android 磁盘挂载Vold机制的核心调度,上下连接的中转站!

         在system/vold/main.cpp的主函数中

   /* Create our singleton managers */    if (!(vm = VolumeManager::Instance())) {//构造VolumeManager        SLOGE("Unable to create VolumeManager");        exit(1);    };........................ vm->setBroadcaster((SocketListener *) cl);......................... if (vm->start()) {//没有做什么动作        SLOGE("Unable to start VolumeManager (%s)", strerror(errno));        exit(1);    }    if (process_config(vm)) {        SLOGE("Error reading configuration (%s)... continuing anyways", strerror(errno));    }

VolumeManager::VolumeManager() {    mDebug = false;    mVolumes = new VolumeCollection();//在构造函数中new一个VolumeCollection用来保存Volume的容器    mActiveContainers = new AsecIdCollection();//活动容器,mount/unmount asec obb时的记录    mBroadcaster = NULL;//指向SocketListener,用于发送挂载事件    mUmsSharingCount = 0;    mSavedDirtyRatio = -1;    // set dirty ratio to 0 when UMS is active    mUmsDirtyRatio = 0;    mVolManagerDisabled = 0;}

加打印看了一下process_config(vm),发现是去解析fstab.madison文件,但是在真正做动作的地方没有跑进去,也就是说main函数里面最主要的就是new了一个VolumeCollection容器

然后接着看上篇接收到kernel的uevent后的动作!

vm->handleBlockEvent(evt);
void VolumeManager::handleBlockEvent(NetlinkEvent *evt) {    const char *devpath = evt->findParam("DEVPATH");    const char *devtype = evt->findParam("DEVTYPE");    const char *dn = evt->findParam("DEVNAME");    int major = -1;    int minor = -1;    bool isRawDisk = false;    bool isPartition = false;    int partIdx = -1;    bool isSDCard = false;    char device[255];    char uuid[255];    VolumeCollection::iterator it;    bool hit = false;    static bool preDiskChangeEvent = false;.............    major = atoi(evt->findParam("MAJOR"));    minor = atoi(evt->findParam("MINOR"));........... snprintf(device,255,"/dev/block/vold/%d:%d",major,minor);    SLOGD("Javen.tang handlerBlockEvent major = %d, minor = %d, device = %s, devtype = %s\n", major, minor, device ,devtype);...........if (isRawDisk || isPartition) {        //first find uuid from cache        UUIDCache::Entry *entry = uuidCache.searchEntry(device);        if (evt->getAction() == NetlinkEvent::NlActionAdd) {            mode_t mode = 0660 | S_IFBLK;            dev_t dev = (major << 8) | minor;            //if device has been now added, not add again            if (entry != NULL && entry->uuid != NULL) {                return;            }            if (mknod(device, mode, dev) < 0) {//创建设备索引点                if (errno != EEXIST) {                    return ;                }            }            if (!getVolumeUUID(device, uuid, 255)) {//根据device获取一个uuid        #ifdef NETLINK_DEBUG                SLOGD("can not get the uuid of %s when device add",device);        #endif                return ;            }........    if (!hit) {        static char index = 'a'-1;        char * mountPoint = NULL;        const char *dp = NULL;        Volume *volume = NULL;    #ifdef NETLINK_DEBUG        SLOGW("No volumes handled block event for '%s'", devpath);    #endif        if (evt->getAction() != NetlinkEvent::NlActionAdd) {            return;        }..........} else {                if (preDiskChangeEvent) {                    ++index;                    preDiskChangeEvent = false;                }            }........... else if (isPartition) {                asprintf(&mountPoint,"/mnt/usb/sd%c%i",index,partIdx);//U盘的挂载点            }............ volume = new DirectVolume(this, &rec, flags);            addVolume(volume);//根据挂载点new一个volume,然后add到mVolumes容器中去........... if ( volume->handleBlockEvent(evt) !=0 ) {//然后执行volume->handleBlockEvent(evt)            SLOGD("New add volume fail to handle the event of %s",devpath);        }
注意当我们插上U盘时,会创建两个索引点,一个disk,一个partition,我们真正挂载的是partition

D/Vold    (  976): Javen.tang handlerBlockEvent major = 8, minor = 0, device = /dev/block/vold/8:0, devtype = diskD/Vold    (  976): Javen.tang handlerBlockEvent major = 8, minor = 1, device = /dev/block/vold/8:1, devtype = partition
也就是说在VolumeManager中的handleBlockEvent主要做了这几件事

1、根据主次设备号创建索引点;

2、寻找挂载点,这里U盘的挂载点为/mnt/usb/sd%c%i;

3、根据挂载点创建一个DirectVolume,DirectVolume是继承于Volume,Volume就想当于一个存储设备,new了一个Volume后add到mVolumes这个容器中去;

4、调用volume的handleBlockEvent(evt)函数;

二:DirectVolume

        接着看看DirectVolume的handleBlockEvent(evt)函数!

if (!strcmp(devtype, "disk")) {            handleDiskAdded(dp, evt);        } else {            handlePartitionAdded(dp, evt);        }
void DirectVolume::handlePartitionAdded(const char *devpath, NetlinkEvent *evt) {    int major = atoi(evt->findParam("MAJOR"));    int minor = atoi(evt->findParam("MINOR"));    // MStar Android Patch Begin    char msg[255];    // MStar Android Patch End    int part_num;    //devpath = /devices/platform/Mstar-ehci-1.0/usb4/4-1/4-1:1.0/host1/target1:0:0/1:0:0:0/block/sda/sda1    const char *tmp = evt->findParam("PARTN");    if (tmp) {        part_num = atoi(tmp);    } else {        SLOGW("Kernel block uevent missing 'PARTN'");        part_num = 1;    }.........................  if (getState() != Volume::State_Formatting) {            setState(Volume::State_Idle);            snprintf(msg, sizeof(msg), "Volume %s %s Partition Added (%d:%d)",             getLabel(), getFuseMountpoint(), mDiskMajor, mDiskMinor);            mVm->getBroadcaster()->sendBroadcast(ResponseCode::VolumeDiskInserted,                                                msg, false);        }

void Volume::setState(int state) {    char msg[255];    int oldState = mState;    if (oldState == state) {        SLOGW("Duplicate state (%d)\n", state);        return;    }    if ((oldState == Volume::State_Pending) && (state != Volume::State_Idle)) {        mRetryMount = false;    }    mState = state;    SLOGD("Volume %s state changing %d (%s) -> %d (%s)", mLabel,         oldState, stateToStr(oldState), mState, stateToStr(mState));    snprintf(msg, sizeof(msg),             "Volume %s %s state changed from %d (%s) to %d (%s)", getLabel(),             getFuseMountpoint(), oldState, stateToStr(oldState), mState,             stateToStr(mState));    mVm->getBroadcaster()->sendBroadcast(ResponseCode::VolumeStateChange,                                         msg, false);}
这里主要会发送两个广播到frameworks的MountService中去。

先在Volume::setState中通过mVm->getBroadcaster()->sendBroadcast(ResponseCode::VolumeStateChange,msg, false);发送一个VolumeStateChange类型的广播,代表挂载状态在改变,发送的信息为msg,msg的打印如下:

D/Vold    (  977): Javen.tang setState msg=Volume CAA5-CD0B /mnt/usb/sda1 state changed from 0 (No-Media) to 1 (Idle-Unmounted)
然后接着调用mVm->getBroadcaster()->sendBroadcast(ResponseCode::VolumeDiskInserted,msg, false);发送一个VolumeDiskInserted类型的广播,代表U盘插入的意思,信息也是msg,打印msg信息可以看到:

D/DirectVolume(  977): Javen.tang msg=Volume CAA5-CD0B /mnt/usb/sda1 Partition Added (8:1)

接下来就要到jb4.4-kikat/frameworks/base/services/java/com/android/server/MountService.java的onEvent()方法中去查看接收到广播之后执行的动作了!



0 0
原创粉丝点击