void DirectVolume::handleDiskChanged(const char *devpath, NetlinkEvent *evt) {
    int major = atoi(evt->findParam("MAJOR"));
    int minor = atoi(evt->findParam("MINOR"));
    char nodepath[255];
    int fd = 0;

    if ((major != mDiskMajor) || (minor != mDiskMinor)) {
        return;
    }

    SLOGI("Volume %s disk has changed", getLabel());
    const char *tmp = evt->findParam("NPARTS");
    if (tmp) {
        mDiskNumParts = atoi(tmp);
    } else {
        SLOGW("Kernel block uevent missing 'NPARTS'");
        mDiskNumParts = 1;
    }

    /* int partmask = 0;
    int i;
    for (i = 1; i <= mDiskNumParts; i++) {
        partmask |= (1 << i);
    }
    mPendingPartMap = partmask; */
    mPendingPartNum = mDiskNumParts;
    for (int i = 0; i < MAX_PARTITIONS; i++)
        mPartMinors[i] = -1;

    if (getState() != Volume::State_Formatting) {
        if(evt->findParam("DISK_MEDIA_CHANGE")) {
            xlog_printf(ANDROID_LOG_INFO, LOG_TAG, "UsbPatch: disk change with DISK_MEDIA_CHANGE");
            snprintf(nodepath, sizeof(nodepath), "/dev/block/vold/%d:%d", major, minor);
            xlog_printf(ANDROID_LOG_INFO, LOG_TAG, "UsbPatch: Check device node (%s)existence in (%s)!", nodepath, __func__);

            if (-1 == (fd = open(nodepath, O_RDONLY, 0644)) ) {
                xlog_printf(ANDROID_LOG_WARN, LOG_TAG, "UsbPatch: Node Path (%s) open fail, do unmount, mDiskNumParts=%d!", nodepath, mDiskNumParts);
                unmountVol(true, false);
            } else {
                xlog_printf(ANDROID_LOG_INFO, LOG_TAG, "UsbPatch: Node Path (%s) open success with mDiskNumParts=(%d)!", nodepath, mDiskNumParts);
                close(fd);
            }
        } else {
            if (mDiskNumParts == 0) {
                xlog_printf(ANDROID_LOG_INFO, LOG_TAG, "UsbPatch: possible no partition media inserted, do mount first, mDiskNumParts=%d", mDiskNumParts);
                if(getState() == Volume::State_Idle) {
                    if(mountVol() != 0) {
                        mRetryMount = true;
                    }
                } else {
                    mRetryMount = true;
                    setState(Volume::State_Idle);
                }
            } else {
                xlog_printf(ANDROID_LOG_INFO, LOG_TAG, "UsbPatch: possible need next PartitionAdd uevent comes");
                setState(Volume::State_Pending);
            }
        }
    }
}
void DirectVolume::handlePartitionAdded(const char *devpath, NetlinkEvent *evt) {
    int major = atoi(evt->findParam("MAJOR"));
    int minor = atoi(evt->findParam("MINOR"));

    int part_num;

    const char *tmp = evt->findParam("PARTN");

    if (tmp) {
        part_num = atoi(tmp);
    } else {
        SLOGW("Kernel block uevent missing 'PARTN'");
        part_num = 1;
    }

    if (part_num > MAX_PARTITIONS || part_num < 1) {
        SLOGE("Invalid 'PARTN' value");
        return;
    }

    if (part_num > mDiskNumParts) {
        mDiskNumParts = part_num;
    }

    if (major != mDiskMajor) {
        SLOGE("Partition '%s' has a different major than its disk!", devpath);
        return;
    }
#ifdef PARTITION_DEBUG
    SLOGD("Dv:partAdd: part_num = %d, minor = %d\n", part_num, minor);
#endif
    if (part_num > MAX_PARTITIONS) {
        SLOGE("Dv:partAdd: ignoring part_num = %d (max: %d)\n", part_num, MAX_PARTITIONS-1);
    } else {
        if ((mPartMinors[part_num - 1] == -1) && mPendingPartNum)
            mPendingPartNum--;
        mPartMinors[part_num -1] = minor;
    }
    // mPendingPartMap &= ~(1 << part_num);

    if (!mPendingPartNum) {
#ifdef PARTITION_DEBUG
        SLOGD("Dv:partAdd: Got all partitions - ready to rock!");
#endif
        if (getState() != Volume::State_Formatting) {
            setState(Volume::State_Idle);
            if(mVm->getIpoState() == VolumeManager::State_Ipo_Start) {
                if (mRetryMount == true) {
                    mRetryMount = false;
                    mountVol();
                }
            }
        }
    } else {
#ifdef PARTITION_DEBUG
        SLOGD("Dv:partAdd: pending %d disk", mPendingPartNum);
#endif
    }
}
void DirectVolume::handlePartitionAdded(const char *devpath, NetlinkEvent *evt) {
    int major = atoi(evt->findParam("MAJOR"));
    int minor = atoi(evt->findParam("MINOR"));

    int part_num;

    const char *tmp = evt->findParam("PARTN");

    if (tmp) {
        part_num = atoi(tmp);
    } else {
        SLOGW("Kernel block uevent missing 'PARTN'");
        part_num = 1;
    }

    SLOGD("DirectVolume::handlePartitionAdded -> MAJOR %d, MINOR %d, PARTN %d\n", major, minor, part_num);

    if (part_num > MAX_PARTITIONS || part_num < 1) {
        SLOGE("Invalid 'PARTN' value");
        return;
    }

    if (part_num > mDiskNumParts) {
        mDiskNumParts = part_num;
    }

    if (major != mDiskMajor) {
#ifdef VOLD_DISC_HAS_MULTIPLE_MAJORS
        ValuePair vp;
        vp.major = major;
        vp.part_num = part_num;
        badPartitions.push_back(vp);
        // Errors with internal volume are expected, so do not show them
        if(strcmp(getLabel(), VOLD_INTERNAL_VOLUME))
#endif
        SLOGE("Partition '%s' of '%s' has a different major than its disk!", devpath, getLabel());
#ifndef VOLD_DISC_HAS_MULTIPLE_MAJORS
        return;
#endif
    }
#ifdef PARTITION_DEBUG
    SLOGD("Dv:partAdd: part_num = %d, minor = %d\n", part_num, minor);
#endif
    if (part_num > MAX_PARTITIONS) {
        SLOGE("Dv:partAdd: ignoring part_num = %d (max: %d)\n", part_num, MAX_PARTITIONS);
    } else {
        mPartMinors[part_num -1] = minor;
    }
    mPendingPartMap &= ~(1 << part_num);

    if (!mPendingPartMap) {
#ifdef PARTITION_DEBUG
        SLOGD("Dv:partAdd: Got all partitions - ready to rock!");
#endif
        if (getState() != Volume::State_Formatting) {
            setState(Volume::State_Idle);
            if (mRetryMount == true) {
                mRetryMount = false;
                mountVol();
            }
        }
    } else {
#ifdef PARTITION_DEBUG
        SLOGD("Dv:partAdd: pending mask now = 0x%x", mPendingPartMap);
#endif
    }
}
void DirectVolume::handlePartitionAdded(const char *devpath, NetlinkEvent *evt) {
	bool is_udisk = false;
    int major = atoi(evt->findParam("MAJOR"));
    int minor = atoi(evt->findParam("MINOR"));

    int part_num;

    const char *tmp = evt->findParam("PARTN");

    if (tmp) {
        part_num = atoi(tmp);
    } else {
        SLOGW("Kernel block uevent missing 'PARTN'");
        part_num = 1;
    }

    if (part_num > MAX_PARTITIONS || part_num < 1) {
        SLOGE("Invalid 'PARTN' value");
        return;
    }

	if(strstr(devpath,"pci")&&strstr(devpath,"sd"))
		is_udisk = true;

    if (isMountpointMounted(getMountpoint())||
			(is_udisk&&(getState()!=Volume::State_Pending))) {
		SLOGD("not the first udisk in handlePartitionAdded %d %d\n",major,minor);
		mountExtraPartition(major,minor);
		return;

	}



    if (part_num > mDiskNumParts) {
        mDiskNumParts = part_num;
    }

    if (major != mDiskMajor) {
        SLOGE("Partition '%s' has a different major than its disk!", devpath);
        return;
    }
#ifdef PARTITION_DEBUG
    SLOGD("Dv:partAdd: part_num = %d, minor = %d\n", part_num, minor);
#endif
    if (part_num >= MAX_PARTITIONS) {
        SLOGE("Dv:partAdd: ignoring part_num = %d (max: %d)\n", part_num, MAX_PARTITIONS-1);
    } else {
        mPartMinors[part_num -1] = minor;
    }


	if(mPendingPartMap>1)
		mPendingPartMap = mPendingPartMap>>1;
    //mPendingPartMap &= ~(1 << part_num);

    if (mPendingPartMap==0x1) {
#ifdef PARTITION_DEBUG
        SLOGD("Dv:partAdd: Got all partitions - ready to rock!");
#endif
        if (getState() != Volume::State_Formatting) {
            setState(Volume::State_Idle);
            if (mRetryMount == true) {
                mRetryMount = false;
                mountVol();
            }
        }
    } else {
#ifdef PARTITION_DEBUG
        SLOGD("Dv:partAdd: pending mask now = 0x%x", mPendingPartMap);
#endif
    }
}