既上面两篇博客,继续分析vold、对外置SD卡和OTG的分析:


一、process_config函数

上一篇我们再main函数中分析了VolumeManager的start函数,这次我们接下来分析process_config函数

static int process_config(VolumeManager *vm) {    std::string path(android::vold::DefaultFstabPath());    fstab = fs_mgr_read_fstab(path.c_str());    if (!fstab) {        PLOG(ERROR) << "Failed to open default fstab " << path;        return -1;    }    /* Loop through entries looking for ones that vold manages */    bool has_adoptable = false;    for (int i = 0; i < fstab->num_entries; i++) {        if (fs_mgr_is_voldmanaged(&fstab->recs[i])) {            if (fs_mgr_is_nonremovable(&fstab->recs[i])) {                LOG(WARNING) << "nonremovable no longer supported; ignoring volume";                continue;            }            std::string sysPattern(fstab->recs[i].blk_device);            std::string nickname(fstab->recs[i].label);            int flags = 0;            if (fs_mgr_is_encryptable(&fstab->recs[i])) {                flags |= android::vold::Disk::Flags::kAdoptable;                has_adoptable = true;            }            if (fs_mgr_is_noemulatedsd(&fstab->recs[i])                    || property_get_bool("vold.debug.default_primary", false)) {                flags |= android::vold::Disk::Flags::kDefaultPrimary;            }    PLOG(ERROR) << "process_config:" <<" sysPattern:" << sysPattern <<" nickname:" << nickname<<" end";            vm->addDiskSource(std::shared_ptr(                    new VolumeManager::DiskSource(sysPattern, nickname, flags)));        }    }    property_set("vold.has_adoptable", has_adoptable ? "1" : "0");    return 0;}

process_config函数就是遍历fstab文件,下面就是fstab文件

# Android fstab file.#                                               # The filesystem that contains the filesystem checker binary (typically /system) cannot# specify MF_CHECK, and must come before any filesystems that do specify MF_CHECK/dev/block/platform/comip-mmc.1/by-name/system                    /system          ext4    ro,barrier=1                                                    wait/dev/block/platform/comip-mmc.1/by-name/cache                     /cache           ext4    noatime,nosuid,nodev,barrier=1,data=ordered                     wait,check/dev/block/platform/comip-mmc.1/by-name/userdata                  /data            ext4    noatime,nosuid,nodev,barrier=1,data=ordered,noauto_da_alloc     wait,check,encryptable=footer#/dev/block/platform/comip-mmc.1/by-name/amt                      /amt             ext4    rw                                                              wait/devices/platform/comip-mmc.0/mmc_host/mmc1/*                       auto             vfat    defaults                                                        voldmanaged=sdcard1:auto,encryptable=false/devices/a0400000.usb_hcd/usb1/*                                    auto      vfat    defaults        voldmanaged=usbotg:auto,noemulatedsd/dev/block/mmcblk1p1                                              /sdcard                vfat  defaults  recoveryonly/dev/block/platform/comip-mmc.1/by-name/kernel                                /kernel          emmc        defaults    defaults/dev/block/platform/comip-mmc.1/by-name/ramdisk                   /boot                  emmc    defaults    defaults/dev/block/platform/comip-mmc.1/by-name/ramdisk_recovery          /recovery        emmc    defaults    defaults/dev/block/platform/comip-mmc.1/by-name/ramdisk_amt1              /ramdisk_amt1    emmc    defaults    defaults/dev/block/platform/comip-mmc.1/by-name/ramdisk_amt3              /ramdisk_amt3    emmc    defaults    defaults/dev/block/platform/comip-mmc.1/by-name/kernel_recovery           /kernel_recovery emmc    defaults    defaults/dev/block/platform/comip-mmc.1/by-name/logo                      /logo            emmc    defaults    defaults/dev/block/platform/comip-mmc.1/by-name/misc                      /misc            emmc    defaults    defaults/dev/block/platform/comip-mmc.1/by-name/fota                      /fota            emmc    defaults    defaults/dev/block/platform/comip-mmc.1/by-name/modemarm                  /modemarm        emmc    defaults    defaults/dev/block/platform/comip-mmc.1/by-name/modemdsp                  /modemdsp        emmc    defaults    defaults/dev/block/mmcblk0boot0                                           /uboot           emmc    defaults    defaults/dev/block/platform/comip-mmc.1/by-name/lcboot                          /lcboot          emmc    defaults    defaults/dev/block/zram0                                                  none          swap    defaults        zramsize=268435456

简单说上面的函数就是遍历fstab文件中有voldmanaged的那项,然后新建一个DiskSource对象,加入volumeManager。

我们再来看看上面加的log的打印

01-01 09:00:25.347   164   164 E vold    :process_config: sysPattern:/devices/platform/comip-mmc.0/mmc_host/mmc1/* nickname:sdcard1 end: Success01-01 09:00:25.347   164   164 E vold    :process_config: sysPattern:/devices/a0400000.usb_hcd/usb1/* nickname:usbotg end: Success

一个nickname是sdcard1,另一个是usbotg。

二、Disk的创建

下面我们来看下kernel对sdcard的检测到之后,通知vold后,vold如何操作。

kernel收到插入sd或者otg的event后,先到NetlinkHandler的onEvent函数,这个在之前分析android5.1的时候分析过了,不再详述。

void NetlinkHandler::onEvent(NetlinkEvent *evt) {    VolumeManager *vm = VolumeManager::Instance();    const char *subsys = evt->getSubsystem();    if (!subsys) {        SLOGW("No subsystem found in netlink event");        return;    }    if (!strcmp(subsys, "block")) {        vm->handleBlockEvent(evt);    }}

然后就到VolumeManager的handleBlockEvent函数,我们先看add的处理

void VolumeManager::handleBlockEvent(NetlinkEvent *evt) {    std::lock_guard lock(mLock);    if (mDebug) {        LOG(VERBOSE) << "----------------";        LOG(VERBOSE) << "handleBlockEvent with action " << (int) evt->getAction();        evt->dump();    }    std::string eventPath(evt->findParam("DEVPATH"));    std::string devType(evt->findParam("DEVTYPE"));    if (devType != "disk") return;    int major = atoi(evt->findParam("MAJOR"));    int minor = atoi(evt->findParam("MINOR"));    dev_t device = makedev(major, minor);    switch (evt->getAction()) {    case NetlinkEvent::Action::kAdd: {        for (auto source : mDiskSources) {//把之前在process_config中加入的disksources的资源遍历,看是否有匹配的            if (source->matches(eventPath)) {                // For now, assume that MMC devices are SD, and that                // everything else is USB                int flags = source->getFlags();                if (major == kMajorBlockMmc) {                    flags |= android::vold::Disk::Flags::kSd;                } else {                    flags |= android::vold::Disk::Flags::kUsb;                }                auto disk = new android::vold::Disk(eventPath, device,                        source->getNickname(), flags);                disk->create();                mDisks.push_back(std::shared_ptr(disk));                break;            }        }        break;    }

遍历之前在process_config函数中放入VolumeManager的DiskSource,看看是否有匹配的。匹配的新建一个Disk对象,放入VolumeManager的mDisks中。并且调用disk的create函数:

status_t Disk::create() {    CHECK(!mCreated);    mCreated = true;    notifyEvent(ResponseCode::DiskCreated, StringPrintf("%d", mFlags));    readMetadata();    readPartitions();    return OK;}

在create函数中,先给MountService发送了DiskCreated的消息,我们看看MountService是如何处理的?

在MountService中在onEventLocked中对DiskCreated处理,也是放在mDisks变量中

    private boolean onEventLocked(int code, String raw, String[] cooked) {        switch (code) {            case VoldResponseCode.DISK_CREATED: {                if (cooked.length != 3) break;                final String id = cooked[1];                int flags = Integer.parseInt(cooked[2]);                if (SystemProperties.getBoolean(StorageManager.PROP_FORCE_ADOPTABLE, false)                        || mForceAdoptable) {                    flags |= DiskInfo.FLAG_ADOPTABLE;                }                mDisks.put(id, new DiskInfo(id, flags));                break;            }

下面继续分析disk的create函数,看Disk::readMetadata函数

status_t Disk::readMetadata() {    mSize = -1;    mLabel.clear();    int fd = open(mDevPath.c_str(), O_RDONLY | O_CLOEXEC);    if (fd != -1) {        if (ioctl(fd, BLKGETSIZE64, &mSize)) {            mSize = -1;        }        close(fd);    }    switch (major(mDevice)) {    case kMajorBlockScsiA: case kMajorBlockScsiB: case kMajorBlockScsiC: case kMajorBlockScsiD:    case kMajorBlockScsiE: case kMajorBlockScsiF: case kMajorBlockScsiG: case kMajorBlockScsiH:    case kMajorBlockScsiI: case kMajorBlockScsiJ: case kMajorBlockScsiK: case kMajorBlockScsiL:    case kMajorBlockScsiM: case kMajorBlockScsiN: case kMajorBlockScsiO: case kMajorBlockScsiP: {        std::string path(mSysPath + "/device/vendor");        std::string tmp;        if (!ReadFileToString(path, &tmp)) {            PLOG(WARNING) << "Failed to read vendor from " << path;            return -errno;        }        mLabel = tmp;        break;    }    case kMajorBlockMmc: {        std::string path(mSysPath + "/device/manfid");        std::string tmp;        if (!ReadFileToString(path, &tmp)) {            PLOG(WARNING) << "Failed to read manufacturer from " << path;            return -errno;        }        uint64_t manfid = strtoll(tmp.c_str(), nullptr, 16);        // Our goal here is to give the user a meaningful label, ideally        // matching whatever is silk-screened on the card.  To reduce        // user confusion, this list doesn't contain white-label manfid.        switch (manfid) {        case 0x000003: mLabel = "SanDisk"; break;        case 0x00001b: mLabel = "Samsung"; break;        case 0x000028: mLabel = "Lexar"; break;        case 0x000074: mLabel = "Transcend"; break;        }        break;    }    default: {        LOG(WARNING) << "Unsupported block major type" << major(mDevice);        return -ENOTSUP;    }    }    notifyEvent(ResponseCode::DiskSizeChanged, StringPrintf("%" PRId64, mSize));    notifyEvent(ResponseCode::DiskLabelChanged, mLabel);    notifyEvent(ResponseCode::DiskSysPathChanged, mSysPath);    return OK;}

这个函数主要获取一些参数,然后发送给MountService,而MountService的处理如下,主要是把disk的参数修改下

            case VoldResponseCode.DISK_SIZE_CHANGED: {                if (cooked.length != 3) break;                final DiskInfo disk = mDisks.get(cooked[1]);                if (disk != null) {                    disk.size = Long.parseLong(cooked[2]);                }                break;            }            case VoldResponseCode.DISK_LABEL_CHANGED: {                final DiskInfo disk = mDisks.get(cooked[1]);                if (disk != null) {                    final StringBuilder builder = new StringBuilder();                    for (int i = 2; i < cooked.length; i++) {                        builder.append(cooked[i]).append(' ');                    }                    disk.label = builder.toString().trim();                }                break;            }            case VoldResponseCode.DISK_SCANNED: {                if (cooked.length != 2) break;                final DiskInfo disk = mDisks.get(cooked[1]);                if (disk != null) {                    onDiskScannedLocked(disk);                }                break;            }            case VoldResponseCode.DISK_SYS_PATH_CHANGED: {                if (cooked.length != 3) break;                final DiskInfo disk = mDisks.get(cooked[1]);                if (disk != null) {                    disk.sysPath = cooked[2];                }                br

下面我们继续看Disk的readParttitions函数

status_t Disk::readPartitions() {    int8_t maxMinors = getMaxMinors();    if (maxMinors < 0) {        return -ENOTSUP;    }    destroyAllVolumes();    // Parse partition table    std::vector cmd;    cmd.push_back(kSgdiskPath);    cmd.push_back("--android-dump");    cmd.push_back(mDevPath);    std::vector output;    status_t res = ForkExecvp(cmd, output);    if (res != OK) {        LOG(WARNING) << "sgdisk failed to scan " << mDevPath;        notifyEvent(ResponseCode::DiskScanned);        mJustPartitioned = false;        return res;    }    Table table = Table::kUnknown;    bool foundParts = false;    for (auto line : output) {        char* cline = (char*) line.c_str();        char* token = strtok(cline, kSgdiskToken);        if (token == nullptr) continue;        if (!strcmp(token, "DISK")) {            const char* type = strtok(nullptr, kSgdiskToken);            if (!strcmp(type, "mbr")) {                table = Table::kMbr;            } else if (!strcmp(type, "gpt")) {                table = Table::kGpt;            }        } else if (!strcmp(token, "PART")) {            foundParts = true;            int i = strtol(strtok(nullptr, kSgdiskToken), nullptr, 10);            if (i <= 0 || i > maxMinors) {                LOG(WARNING) << mId << " is ignoring partition " << i                        << " beyond max supported devices";                continue;            }            dev_t partDevice = makedev(major(mDevice), minor(mDevice) + i);            if (table == Table::kMbr) {                const char* type = strtok(nullptr, kSgdiskToken);                switch (strtol(type, nullptr, 16)) {                case 0x06: // FAT16                case 0x0b: // W95 FAT32 (LBA)                case 0x0c: // W95 FAT32 (LBA)                case 0x0e: // W95 FAT16 (LBA)                    createPublicVolume(partDevice);                    break;                }            } else if (table == Table::kGpt) {                const char* typeGuid = strtok(nullptr, kSgdiskToken);                const char* partGuid = strtok(nullptr, kSgdiskToken);                if (!strcasecmp(typeGuid, kGptBasicData)) {                    createPublicVolume(partDevice);                } else if (!strcasecmp(typeGuid, kGptAndroidExpand)) {                    createPrivateVolume(partDevice, partGuid);                }            }        }    }    // Ugly last ditch effort, treat entire disk as partition    if (table == Table::kUnknown || !foundParts) {        LOG(WARNING) << mId << " has unknown partition table; trying entire device";        std::string fsType;        std::string unused;        if (ReadMetadataUntrusted(mDevPath, fsType, unused, unused) == OK) {            createPublicVolume(mDevice);        } else {            LOG(WARNING) << mId << " failed to identify, giving up";        }    }    notifyEvent(ResponseCode::DiskScanned);    mJustPartitioned = false;    return OK;}

这个函数就主要会createPublicVolume或者createPrivateVolume,然后会通知MountService DiskScanned消息。先看上层对这个消息的处理。

            case VoldResponseCode.DISK_SCANNED: {                if (cooked.length != 2) break;                final DiskInfo disk = mDisks.get(cooked[1]);                if (disk != null) {                    onDiskScannedLocked(disk);                }                break;            }

找到DiskInfo后,调用了onDiskScannedLocked函数

    private void onDiskScannedLocked(DiskInfo disk) {        int volumeCount = 0;        for (int i = 0; i < mVolumes.size(); i++) {            final VolumeInfo vol = mVolumes.valueAt(i);            if (Objects.equals(disk.id, vol.getDiskId())) {                volumeCount++;            }        }        final Intent intent = new Intent(DiskInfo.ACTION_DISK_SCANNED);        intent.addFlags(Intent.FLAG_RECEIVER_REGISTERED_ONLY_BEFORE_BOOT);        intent.putExtra(DiskInfo.EXTRA_DISK_ID, disk.id);        intent.putExtra(DiskInfo.EXTRA_VOLUME_COUNT, volumeCount);        mHandler.obtainMessage(H_INTERNAL_BROADCAST, intent).sendToTarget();        final CountDownLatch latch = mDiskScanLatches.remove(disk.id);        if (latch != null) {            latch.countDown();        }        disk.volumeCount = volumeCount;        mCallbacks.notifyDiskScanned(disk, volumeCount);    }

这个函数中发送了广播,然后通知了回调。


三、CreatePublicVolume

接下来我们主要分析下createPublicVolume和createPrivateVolume两个函数。

先看createPublicVolume函数:

void Disk::createPublicVolume(dev_t device) {    auto vol = std::shared_ptr(new PublicVolume(device));    if (mJustPartitioned) {        LOG(DEBUG) << "Device just partitioned; silently formatting";        vol->setSilent(true);        vol->create();        vol->format("auto");        vol->destroy();        vol->setSilent(false);    }    mVolumes.push_back(vol);    vol->setDiskId(getId());    vol->create();}

这个函数中,先新建了一个PublicVolume,然后让如了Disk的mVolumes中,最后调用了volume的create函数

status_t VolumeBase::create() {    CHECK(!mCreated);    mCreated = true;    status_t res = doCreate();    notifyEvent(ResponseCode::VolumeCreated,            StringPrintf("%d \"%s\" \"%s\"", mType, mDiskId.c_str(), mPartGuid.c_str()));    setState(State::kUnmounted);    return res;}

create函数又回调之前分析过得,给上层发送VolumeCreated消息
只是这个create的doCreate函数在PublicVolume中有实现:

status_t PublicVolume::doCreate() {    return CreateDeviceNode(mDevPath, mDevice);}

然后往MountService发送VolumeCreated后,MountService会往vold发送mount。

status_t VolumeBase::mount() {    if ((mState != State::kUnmounted) && (mState != State::kUnmountable)) {        LOG(WARNING) << getId() << " mount requires state unmounted or unmountable";        return -EBUSY;    }    setState(State::kChecking);    status_t res = doMount();    if (res == OK) {        setState(State::kMounted);    } else {        setState(State::kUnmountable);    }    return res;}

在Volumebase执行mount函数的时候,到doMount是一个虚函数会到PublicVolume的doMount函数

status_t PublicVolume::doMount() {    // TODO: expand to support mounting other filesystems    readMetadata();    if (mFsType != "vfat") {        LOG(ERROR) << getId() << " unsupported filesystem " << mFsType;        return -EIO;    }    if (vfat::Check(mDevPath)) {        LOG(ERROR) << getId() << " failed filesystem check";        return -EIO;    }    // Use UUID as stable name, if available    std::string stableName = getId();    if (!mFsUuid.empty()) {        stableName = mFsUuid;    }    mRawPath = StringPrintf("/mnt/media_rw/%s", stableName.c_str());//挂载地址,stableName为uuid    mFuseDefault = StringPrintf("/mnt/runtime/default/%s", stableName.c_str());    mFuseRead = StringPrintf("/mnt/runtime/read/%s", stableName.c_str());    mFuseWrite = StringPrintf("/mnt/runtime/write/%s", stableName.c_str());    setInternalPath(mRawPath);    if (getMountFlags() & MountFlags::kVisible) {        setPath(StringPrintf("/storage/%s", stableName.c_str()));    } else {        setPath(mRawPath);    }    if (fs_prepare_dir(mRawPath.c_str(), 0700, AID_ROOT, AID_ROOT) ||            fs_prepare_dir(mFuseDefault.c_str(), 0700, AID_ROOT, AID_ROOT) ||            fs_prepare_dir(mFuseRead.c_str(), 0700, AID_ROOT, AID_ROOT) ||            fs_prepare_dir(mFuseWrite.c_str(), 0700, AID_ROOT, AID_ROOT)) {        PLOG(ERROR) << getId() << " failed to create mount points";        return -errno;    }    if (vfat::Mount(mDevPath, mRawPath, false, false, false,//挂载sd卡            AID_MEDIA_RW, AID_MEDIA_RW, 0007, true)) {        PLOG(ERROR) << getId() << " failed to mount " << mDevPath;        return -EIO;    }    if (getMountFlags() & MountFlags::kPrimary) {        initAsecStage();    }    if (!(getMountFlags() & MountFlags::kVisible)) {        // Not visible to apps, so no need to spin up FUSE        return OK;    }    dev_t before = GetDevice(mFuseWrite);    if (!(mFusePid = fork())) {        if (getMountFlags() & MountFlags::kPrimary) {//开启fuse文件系统,让storage下面的sd卡读取直接到mnt下挂载的地址            if (execl(kFusePath, kFusePath,                    "-u", "1023", // AID_MEDIA_RW                    "-g", "1023", // AID_MEDIA_RW                    "-U", std::to_string(getMountUserId()).c_str(),                    "-w",                    mRawPath.c_str(),                    stableName.c_str(),                    NULL)) {                PLOG(ERROR) << "Failed to exec";            }        } else {            if (execl(kFusePath, kFusePath,                    "-u", "1023", // AID_MEDIA_RW                    "-g", "1023", // AID_MEDIA_RW                    "-U", std::to_string(getMountUserId()).c_str(),                    mRawPath.c_str(),                    stableName.c_str(),                    NULL)) {                PLOG(ERROR) << "Failed to exec";            }        }        LOG(ERROR) << "FUSE exiting";        _exit(1);    }    if (mFusePid == -1) {        PLOG(ERROR) << getId() << " failed to fork";        return -errno;    }    while (before == GetDevice(mFuseWrite)) {        LOG(VERBOSE) << "Waiting for FUSE to spin up...";        usleep(50000); // 50ms    }    return OK;}

这个函数我们先看readMetadata函数,会读取各个参数,然后发送到MountService中,在上层会把这些参数保存在DiskInfo中

status_t PublicVolume::readMetadata() {    status_t res = ReadMetadataUntrusted(mDevPath, mFsType, mFsUuid, mFsLabel);    notifyEvent(ResponseCode::VolumeFsTypeChanged, mFsType);    notifyEvent(ResponseCode::VolumeFsUuidChanged, mFsUuid);    notifyEvent(ResponseCode::VolumeFsLabelChanged, mFsLabel);    return res;}

再看下面这段代码,当uuid不为空,statbleName为uuid

    if (!mFsUuid.empty()) {        stableName = mFsUuid;    }

doMount就是把sd卡设备挂载到mnt/media_rw下面创建一个uuid的目录。然后在Storage下面也有一个uuid的目录,用fuse文件系统连接起来。大家可以看上面代码的注释。


四、createPrivateVolume


下面我们再来看Disk的createPrivateVolume方法

void Disk::createPrivateVolume(dev_t device, const std::string& partGuid) {    std::string normalizedGuid;    if (NormalizeHex(partGuid, normalizedGuid)) {        LOG(WARNING) << "Invalid GUID " << partGuid;        return;    }    std::string keyRaw;    if (!ReadFileToString(BuildKeyPath(normalizedGuid), &keyRaw)) {        PLOG(ERROR) << "Failed to load key for GUID " << normalizedGuid;        return;    }    LOG(DEBUG) << "Found key for GUID " << normalizedGuid;    auto vol = std::shared_ptr(new PrivateVolume(device, keyRaw));    if (mJustPartitioned) {        LOG(DEBUG) << "Device just partitioned; silently formatting";        vol->setSilent(true);        vol->create();        vol->format("auto");        vol->destroy();        vol->setSilent(false);    }    mVolumes.push_back(vol);    vol->setDiskId(getId());    vol->setPartGuid(partGuid);    vol->create();}

和PublicVolume类似我们就直接看privateVolume的doMount函数

tatus_t PrivateVolume::doMount() {    if (readMetadata()) {        LOG(ERROR) << getId() << " failed to read metadata";        return -EIO;    }    mPath = StringPrintf("/mnt/expand/%s", mFsUuid.c_str());//mount地址    setPath(mPath);    if (PrepareDir(mPath, 0700, AID_ROOT, AID_ROOT)) {        PLOG(ERROR) << getId() << " failed to create mount point " << mPath;        return -EIO;    }    if (mFsType == "ext4") {//fs类型        int res = ext4::Check(mDmDevPath, mPath);        if (res == 0 || res == 1) {            LOG(DEBUG) << getId() << " passed filesystem check";        } else {            PLOG(ERROR) << getId() << " failed filesystem check";            return -EIO;        }        if (ext4::Mount(mDmDevPath, mPath, false, false, true)) {            PLOG(ERROR) << getId() << " failed to mount";            return -EIO;        }    } else if (mFsType == "f2fs") {        int res = f2fs::Check(mDmDevPath);        if (res == 0) {            LOG(DEBUG) << getId() << " passed filesystem check";        } else {            PLOG(ERROR) << getId() << " failed filesystem check";            return -EIO;        }        if (f2fs::Mount(mDmDevPath, mPath)) {            PLOG(ERROR) << getId() << " failed to mount";            return -EIO;        }    } else {        LOG(ERROR) << getId() << " unsupported filesystem " << mFsType;        return -EIO;    }    LOG(VERBOSE) << "Starting restorecon of " << mPath;    // TODO: find a cleaner way of waiting for restorecon to finish    property_set("selinux.restorecon_recursive", "");    property_set("selinux.restorecon_recursive", mPath.c_str());    char value[PROPERTY_VALUE_MAX];    while (true) {        property_get("selinux.restorecon_recursive", value, "");        if (strcmp(mPath.c_str(), value) == 0) {            break;        }        sleep(1);        LOG(VERBOSE) << "Waiting for restorecon...";    }    LOG(VERBOSE) << "Finished restorecon of " << mPath;    // Verify that common directories are ready to roll    if (PrepareDir(mPath + "/app", 0771, AID_SYSTEM, AID_SYSTEM) ||//创建了各个目录            PrepareDir(mPath + "/user", 0711, AID_SYSTEM, AID_SYSTEM) ||            PrepareDir(mPath + "/media", 0770, AID_MEDIA_RW, AID_MEDIA_RW) ||            PrepareDir(mPath + "/media/0", 0770, AID_MEDIA_RW, AID_MEDIA_RW) ||            PrepareDir(mPath + "/local", 0751, AID_ROOT, AID_ROOT) ||            PrepareDir(mPath + "/local/tmp", 0771, AID_SHELL, AID_SHELL)) {        PLOG(ERROR) << getId() << " failed to prepare";        return -EIO;    }    // Create a new emulated volume stacked above us, it will automatically    // be destroyed during unmount    std::string mediaPath(mPath + "/media");//只把media传过去,fuse给storage    auto vol = std::shared_ptr(            new EmulatedVolume(mediaPath, mRawDevice, mFsUuid));    addVolume(vol);    vol->create();    return OK;}

当然最后完成后setState(kMounted)会通知MountService,上层只会调用onVolumeStateChangedLocked会发送广播并且通知回调。


这样整个vold主要的流程分析完了,当然这边没有分析fuse的相关内容,等以后再分析吧!



更多相关文章

  1. Android(安卓)display架构分析(5-8)
  2. android 多线程 UI 入门
  3. Android中Framgment的构造函数
  4. Android7.0启动SystemServer进程
  5. Surface与SurfaceHolder.Callback
  6. Android(安卓)图片加载框架Glide缓存原理源码分析
  7. Android(安卓)-- 网络管理分析
  8. Android事件分发中的ViewGroup
  9. HAL层开发基础 && Android(安卓)HAL module执行过程分析

随机推荐

  1. HTML基础详解(下)
  2. CSS将div内容垂直居中案例总结
  3. php基于redis的分布式锁实例详解
  4. PHP中的输出缓冲控制详解
  5. 详解PHP使用OSS上传文件
  6. 如何使用SublimeText3配置 PHP IDE环境
  7. 如何在thinkphp中使用windows计划任务定
  8. 布局实战小结
  9. PHP输出缓冲与header发送问题详解
  10. 如何画动漫人物侧脸?人物侧脸画法教程!