深入Mountservice vold(六) handleDiskRemoved handlePartitionRemoved(and5.1)

来源:互联网 发布:is语音软件下载 编辑:程序博客网 时间:2024/05/18 12:38

今天我们来看看vold的拔走存储设备的两个函数handleDiskRemoved handlePartitionRemoved

在vold中,当拔走sd卡,或者拔走otg的u盘等会调用



DirectVolume::handleBlockEvent 函数里的handleDiskRemoved 和 handlePartitionRemoved函数:

            } else if (action == NetlinkEvent::NlActionRemove) {                if (!strcmp(devtype, "disk")) {                    handleDiskRemoved(dp, evt);//去除磁盘                } else {                    handlePartitionRemoved(dp, evt);//去除分区                }            }

正常流程是先调用handlePartitionRemoved,然后再调用handleDiskRemoved函数

先看handlePartitionRemoved函数

void DirectVolume::handlePartitionRemoved(const char * /*devpath*/,                                          NetlinkEvent *evt) {    int major = atoi(evt->findParam("MAJOR"));    int minor = atoi(evt->findParam("MINOR"));    char msg[255];    int state;    SLOGD("Volume %s %s partition %d:%d removed\n", getLabel(), getMountpoint(), major, minor);    /*     * The framework doesn't need to get notified of     * partition removal unless it's mounted. Otherwise     * the removal notification will be sent on the Disk     * itself     */    state = getState();    if (state != Volume::State_Mounted && state != Volume::State_Shared) {        return;    }            if ((dev_t) MKDEV(major, minor) == mCurrentlyMountedKdev) {        /*         * Yikes, our mounted partition is going away!         */        bool providesAsec = (getFlags() & VOL_PROVIDES_ASEC) != 0;        if (providesAsec && mVm->cleanupAsec(this, true)) {            SLOGE("Failed to cleanup ASEC - unmount will probably fail!");        }        snprintf(msg, sizeof(msg), "Volume %s %s bad removal (%d:%d)",                 getLabel(), getFuseMountpoint(), major, minor);        mVm->getBroadcaster()->sendBroadcast(ResponseCode::VolumeBadRemoval,                                             msg, false);        if (Volume::unmountVol(true, false)) {//走unmount流程            SLOGE("Failed to unmount volume on bad removal (%s)",                  strerror(errno));            // XXX: At this point we're screwed for now        } else {            SLOGD("Crisis averted");        }    } else if (state == Volume::State_Shared) {//开启大容量存储的时候,已经是unmount了        /* removed during mass storage */        snprintf(msg, sizeof(msg), "Volume %s bad removal (%d:%d)",                 getLabel(), major, minor);        mVm->getBroadcaster()->sendBroadcast(ResponseCode::VolumeBadRemoval,                                             msg, false);        if (mVm->unshareVolume(getLabel(), "ums")) {//关闭大容量存储            SLOGE("Failed to unshare volume on bad removal (%s)",                strerror(errno));        } else {            SLOGD("Crisis averted");        }    }}
再看handleDiskRemoved函数

void DirectVolume::handleDiskRemoved(const char * /*devpath*/,                                     NetlinkEvent *evt) {    int major = atoi(evt->findParam("MAJOR"));    int minor = atoi(evt->findParam("MINOR"));    char msg[255];    bool enabled;    if (mVm->shareEnabled(getLabel(), "ums", &enabled) == 0 && enabled) {//如果开启大容量存储,这种情况只有在otg插u盘开启大容量存储的时候。直接到这函数,而不走handlePartitionRemoved,因为有的u盘可能没有分区就不走handlePartitionRemoved了        mVm->unshareVolume(getLabel(), "ums");    }    SLOGD("Volume %s %s disk %d:%d removed\n", getLabel(), getMountpoint(), major, minor);    snprintf(msg, sizeof(msg), "Volume %s %s disk removed (%d:%d)",             getLabel(), getFuseMountpoint(), major, minor);    mVm->getBroadcaster()->sendBroadcast(ResponseCode::VolumeDiskRemoved,// 发送到MountService                                             msg, false);    setState(Volume::State_NoMedia);//改变volume的状态}

但是原生有问题,有时候otg插U盘,这样直接把调U盘的话,如果有的U盘没有分区,就直接走handleDiskRemoved。这样handleDiskRemoved函数中又没有执行unmount流程,下次再要挂载就会出问题。

所以要修改的话可以这样做,如果没有分区的话,也要走卸载流程

void DirectVolume::handleDiskRemoved(const char * /*devpath*/,                                     NetlinkEvent *evt) {    int major = atoi(evt->findParam("MAJOR"));    int minor = atoi(evt->findParam("MINOR"));    char msg[255];    bool enabled;    if (mVm->shareEnabled(getLabel(), "ums", &enabled) == 0 && enabled) {        mVm->unshareVolume(getLabel(), "ums");    }    SLOGD("Volume %s %s disk %d:%d removed\n", getLabel(), getMountpoint(), major, minor);    snprintf(msg, sizeof(msg), "Volume %s %s disk removed (%d:%d)",             getLabel(), getFuseMountpoint(), major, minor);    mVm->getBroadcaster()->sendBroadcast(ResponseCode::VolumeDiskRemoved,                                             msg, false);    //everytime handleDiskRemoved do an umount action first.    if (mDiskNumParts == 0) {//新增,没有分区        SLOGI("handleDiskRemoved: mDiskNumParts is 0 need to do an umount");        if (mVm->cleanupAsec(this, true)) {            SLOGE("handleDiskRemoved: Failed to cleanup ASEC - unmount will probably fail!");        }        if (Volume::unmountVol(true, false)) {            SLOGE("handleDiskRemoved: Failed to unmount volume on bad removal (%s)",strerror(errno));        } else {            SLOGD("handleDiskRemoved: Crisis averted");        }    }    setState(Volume::State_NoMedia);}


我们再来看看MountService对这两个函数发给它的消息的处理,在onEvent函数中:

else if (code == VoldResponseCode.VolumeDiskRemoved) {//正常先走badremoval,再走这                /*                 * This event gets trumped if we're already in BAD_REMOVAL state                 */                if (getVolumeState(path).equals(Environment.MEDIA_BAD_REMOVAL)) {//正常流程直接结束了                    return true;                }                /* Send the media unmounted event first */                if (DEBUG_EVENTS) Slog.i(TAG, "Sending unmounted event first");                updatePublicVolumeState(volume, Environment.MEDIA_UNMOUNTED);//如果走这是,先不是走的badremoval。比如没有分区的存储设备remove                sendStorageIntent(Intent.ACTION_MEDIA_UNMOUNTED, volume, UserHandle.ALL);                if (DEBUG_EVENTS) Slog.i(TAG, "Sending media removed");                updatePublicVolumeState(volume, Environment.MEDIA_REMOVED);                action = Intent.ACTION_MEDIA_REMOVED;            } else if (code == VoldResponseCode.VolumeBadRemoval) {//正常流程是先走这                if (DEBUG_EVENTS) Slog.i(TAG, "Sending unmounted event first");                /* Send the media unmounted event first */                updatePublicVolumeState(volume, Environment.MEDIA_UNMOUNTED);//先变成unmounted状态                sendStorageIntent(Intent.ACTION_MEDIA_UNMOUNTED, volume, UserHandle.ALL);                if (DEBUG_EVENTS) Slog.i(TAG, "Sending media bad removal");                updatePublicVolumeState(volume, Environment.MEDIA_BAD_REMOVAL);//改成badremoval                action = Intent.ACTION_MEDIA_BAD_REMOVAL;            }



1 0
原创粉丝点击