詳細Mountservice vold(六)handleDiskRemoved handlePartitionRemoved(and 5.1)

7426 ワード

今日は、voldがストレージデバイスを抜いた2つの関数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
", 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
", 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
", 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関数で2つの関数に送信したメッセージの処理を見てみましょう.
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;
            }