Android9.0版本Vold服务源码分析

Vold: Volume Daemon,用于管理和控制Android平台外部存储设备的后台进程,这些管理和控制,包括SD卡的插拔事件检测/SD卡挂载/卸载/格式化等.

9.0以前framework java层(StorageManagerService)和native层(Vold)的通信是socket,9.0以后使用binder通信.本文通过SD卡挂载流程,分析binder在vold服务中的使用.

vold服务在开机的时候会启动.定义于system/vold/vold.rc文件中:
service vold /system/bin/vold \
        --blkid_context=u:r:blkid:s0 --blkid_untrusted_context=u:r:blkid_untrusted:s0 \
        --fsck_context=u:r:fsck:s0 --fsck_untrusted_context=u:r:fsck_untrusted:s0
    class core
    ioprio be 2
    writepid /dev/cpuset/foreground/tasks
    shutdown critical
    group reserved_disk

被init进程启动后,将调用system/vold/main.cpp中的main函数,然后初始化VolumeManager,NetlinkManager等等.初始化Vold服务.

在看下StorageManagerService的初始化.StorageManagerService由SystemServer启动,我们简单看看它的启动流程:

//调用SystemServiceManager的startService 
mSystemServiceManager.startService(STORAGE_MANAGER_SERVICE_CLASS);

最终的实现如下:
public void startService(@NonNull final SystemService service) {
        // Register it.
        mServices.add(service);
        // Start it.
        long time = SystemClock.elapsedRealtime();
        try {
            //调用服务的onStart方法.
            service.onStart();
        } catch (RuntimeException ex) {
            throw new RuntimeException("Failed to start service " + service.getClass().getName()
                    + ": onStart threw an exception", ex);
        }
        warnIfTooLong(SystemClock.elapsedRealtime() - time, service, "onStart");
    }

        //StorageManagerService的onStart方法如下:
        @Override
        public void onStart() {
            //创建StorageManagerService
            mStorageManagerService = new StorageManagerService(getContext());
            //将StorageManagerService注册到ServiceManager中
            publishBinderService("mount", mStorageManagerService);
            //调用StorageManagerService的start方法
            mStorageManagerService.start();
        }

        private void start() {
            connect();
        }

    //主要建立和Vold的通信,获取mVold对象,与Vold进程通信.
    private void connect() {
        IBinder binder = ServiceManager.getService("storaged");
        if (binder != null) {
            try {
                //为binder对象设置死亡代理。当binder死亡后重新建立连接.
                binder.linkToDeath(new DeathRecipient() {
                    @Override
                    public void binderDied() {
                        Slog.w(TAG, "storaged died; reconnecting");
                        mStoraged = null;
                        connect();
                    }
                }, 0);
            } catch (RemoteException e) {
                binder = null;
            }
        }

        if (binder != null) {
            mStoraged = IStoraged.Stub.asInterface(binder);
        } else {
            Slog.w(TAG, "storaged not found; trying again");
        }

        binder = ServiceManager.getService("vold");
        if (binder != null) {
            try {
                //为binder对象设置死亡代理。当binder死亡后重新建立连接.
                binder.linkToDeath(new DeathRecipient() {
                    @Override
                    public void binderDied() {
                        Slog.w(TAG, "vold died; reconnecting");
                        mVold = null;
                        connect();
                    }
                }, 0);
            } catch (RemoteException e) {
                binder = null;
            }
        }

        if (binder != null) {
            //通过binder机制,获取mVold对象(mVold就是IVold对象,这是一个代理类,具体实现在VoldNativeService.cpp),从而和Vold进程进行通信.
            mVold = IVold.Stub.asInterface(binder);
            try {
                //mListener是IVoldListener的具体实现,当vold进程中相关事件改变通过IVoldListener这个代理,通知StorageManagerService处理.
                mVold.setListener(mListener);
            } catch (RemoteException e) {
                mVold = null;
                Slog.w(TAG, "vold listener rejected; trying again", e);
            }
        } else {
            Slog.w(TAG, "vold not found; trying again");
        }

        if (mStoraged == null || mVold == null) {
            BackgroundThread.getHandler().postDelayed(() -> {
                connect();
            }, DateUtils.SECOND_IN_MILLIS);
        } else {
            onDaemonConnected();
        }
    }

至此,StorageManagerService和Vold进程启动并建立和通信.

在Android9.0:/system/vold/binder/android/os/路径下多了如下几个文件,用于binder通信,关于binder通信就不在过多介绍,网上有很多优秀的资料,大家可以查找阅读.
IVold.aidl    
IVoldListener.aidl    
IVoldTaskListener.aidl

说下VoldNativeService.cpp这个文件,是IVold的具体实现.例如当mVold这个代理对象去调用mount方法,通过binder机制最终调用到VoldNativeService的mount方法.从而实现跨进程通信,有兴趣的同学可以自己研究下中间调用过程这里不在叙述.

下面说下9.0上SD卡的挂载流程.

先来一张9.0SD卡挂载流程图: 

Android9.0版本Vold服务源码分析_第1张图片

我们知道Vold服务初始化的时候执行main函数,会初始化NetlinkManager,执行start方法,其中会创建一个NetlinkHandler,当底层Kernel发送消息Uevent,经过一系列处理,最终调用VolumeManager的handleBlockEvent处理消息.
其实NetlinkManager启动后就是创建一个可以接收Kernel消息的socket,并以此socket构建并启动NetlinkHandler。 
可以预见NetlinkHandler将用来处理socket收到的信息。

void NetlinkHandler::onEvent(NetlinkEvent *evt) {
    VolumeManager *vm = VolumeManager::Instance();
    //判断当前的Uevent消息是什么类型
    const char *subsys = evt->getSubsystem();

    if (!subsys) {
        LOG(WARNING) << "No subsystem found in netlink event";
        return;
    }
   
    //如果subsys类型是块设备,就调用handleBlockEvent处理该消息
    if (std::string(subsys) == "block") {
        vm->handleBlockEvent(evt);
    }
}
下面vold服务开始真正处理SD卡挂载流程.
void VolumeManager::handleBlockEvent(NetlinkEvent *evt) {
    std::lock_guard lock(mLock);

...

    std::string eventPath(evt->findParam("DEVPATH")?evt->findParam("DEVPATH"):"");
    std::string devType(evt->findParam("DEVTYPE")?evt->findParam("DEVTYPE"):"");
    //设备Type不为disk就返回
    if (devType != "disk") return;
    //major和minor分别表示该设备的主次设备号,二者联合起来可以识别一个设备.
    int major = std::stoi(evt->findParam("MAJOR"));
    int minor = std::stoi(evt->findParam("MINOR"));
    dev_t device = makedev(major, minor);

    switch (evt->getAction()) {
    case NetlinkEvent::Action::kAdd: {
        for (const auto& source : mDiskSources) {
            if (source->matches(eventPath)) {
                // For now, assume that MMC and virtio-blk (the latter is
                // emulator-specific; see Disk.cpp for details) devices are SD,
                // and that everything else is USB
                int flags = source->getFlags();
                if (major == kMajorBlockMmc
                    || (android::vold::IsRunningInEmulator()
                    && major >= (int) kMajorBlockExperimentalMin
                    && major <= (int) kMajorBlockExperimentalMax)) {
                    flags |= android::vold::Disk::Flags::kSd;
                } else {
                    flags |= android::vold::Disk::Flags::kUsb;
                }
                //新建一个Disk,用来保存当前磁盘信息.
                auto disk = new android::vold::Disk(eventPath, device,
                        source->getNickname(), flags);
                handleDiskAdded(std::shared_ptr(disk));
                break;
            }
        }
        break;
    }
    ...
}
//处理磁盘插入,主要调用Disk.cpp的create方法.初始化Disk.
void VolumeManager::handleDiskAdded(const std::shared_ptr& disk) {
    // For security reasons, if secure keyguard is showing, wait
    // until the user unlocks the device to actually touch it
    if (mSecureKeyguardShowing) {
        LOG(INFO) << "Found disk at " << disk->getEventPath()
                << " but delaying scan due to secure keyguard";
        mPendingDisks.push_back(disk);
    } else {
        disk->create();
        mDisks.push_back(disk);
    }
}	

status_t Disk::create() {
    CHECK(!mCreated);
    mCreated = true;
    //onDiskCreated,通过binder机制,通知StorageManagerService磁盘创建
    auto listener = VolumeManager::Instance()->getListener();
    if (listener) listener->onDiskCreated(getId(), mFlags);
    //检查文件系统格式和读取文件分区列表.
    readMetadata();
    readPartitions();
...
    return OK;
}

status_t Disk::readPartitions() {
    ...

    Table table = Table::kUnknown;
    bool foundParts = false;
    for (const auto& line : output) {
        auto split = android::base::Split(line, kSgdiskToken);
        auto it = split.begin();
        if (it == split.end()) continue;

        if (*it == "DISK") {
            if (++it == split.end()) continue;
            if (*it == "mbr") {
                table = Table::kMbr;
            } else if (*it == "gpt") {
                table = Table::kGpt;
            } else {
                LOG(WARNING) << "Invalid partition table " << *it;
                continue;
            }
        } else if (*it == "PART") {
            foundParts = true;

            if (++it == split.end()) continue;
            int i = 0;
            if (!android::base::ParseInt(*it, &i, 1, maxMinors)) {
                LOG(WARNING) << "Invalid partition number " << *it;
                continue;
            }
            dev_t partDevice = makedev(major(mDevice), minor(mDevice) + i);

            if (table == Table::kMbr) {
                if (++it == split.end()) continue;
                int type = 0;
                if (!android::base::ParseInt("0x" + *it, &type)) {
                    LOG(WARNING) << "Invalid partition type " << *it;
                    continue;
                }

                switch (type) {

                    case 0x06:  // FAT16
                    case 0x07:  // HPFS/NTFS/exFAT
                    case 0x0b:  // W95 FAT32 (LBA)
                    case 0x0c:  // W95 FAT32 (LBA)
                    case 0x0e:  // W95 FAT16 (LBA)
                        //创建SD卡的volume信息
                        createPublicVolume(partDevice);
                        break;
                }
            } 
   ...
}

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());
    //调用VolumeBase的create方法.由于PublicVolume是VolumeBase的子类,且具体实现VolumeBase的方法,这里其实调用的是PublicVolume的doCreate方法.
    vol->create();
}


status_t VolumeBase::create() {
    CHECK(!mCreated);

    mCreated = true;
    status_t res = doCreate();
    auto listener = getListener();
     //onVolumeCreated,通过binder机制,通知StorageManagerService创建volume
    if (listener) listener->onVolumeCreated(getId(),
            static_cast(mType), mDiskId, mPartGuid);

    setState(State::kUnmounted);
    return res;
}

        //这里走进了StorageManagerService,
        @Override
        public void onVolumeCreated(String volId, int type, String diskId, String partGuid) {
            synchronized (mLock) {
                final DiskInfo disk = mDisks.get(diskId);
                //保存Volume的信息到VolumeInfo
                final VolumeInfo vol = new VolumeInfo(volId, type, disk, partGuid);
                mVolumes.put(volId, vol);
                onVolumeCreatedLocked(vol);
            }
        }



@GuardedBy("mLock")
    private void onVolumeCreatedLocked(VolumeInfo vol) {
            //这里主要根据设备类型,设置挂载的Flag,最终通过handler发送挂载信息.
            ...
            vol.mountUserId = mCurrentUserId;
            mHandler.obtainMessage(H_VOLUME_MOUNT, vol).sendToTarget();

        } else if (vol.type == VolumeInfo.TYPE_PRIVATE) {
            mHandler.obtainMessage(H_VOLUME_MOUNT, vol).sendToTarget();

        } else {
            Slog.d(TAG, "Skipping automatic mounting of " + vol);
        }
    }

lass StorageManagerServiceHandler extends Handler {
        public StorageManagerServiceHandler(Looper looper) {
            super(looper);
        }

        @Override
        public void handleMessage(Message msg) {
                ....
                case H_VOLUME_MOUNT: {
                    final VolumeInfo vol = (VolumeInfo) msg.obj;
                    if (isMountDisallowed(vol)) {
                        Slog.i(TAG, "Ignoring mount " + vol.getId() + " due to policy");
                        break;
                    }
                    try {
                        slogi(TAG, "Cmd send volume mount from handler " + vol.id + " "
                                + vol.mountFlags + " " + vol.mountUserId);
                        //发送挂载命令,
                        mVold.mount(vol.id, vol.mountFlags, vol.mountUserId);
                        slogi(TAG, "Cmd send volume mount from handler end " + vol.id + " "
                                + vol.mountFlags + " " + vol.mountUserId);
                    } catch (Exception e) {
                        Slog.wtf(TAG, e);
                    }
                    break;
                }
}

mVold.mount在VoldNativeService中处理.
binder::Status VoldNativeService::mount(const std::string& volId, int32_t mountFlags,
        int32_t mountUserId) {
    ENFORCE_UID(AID_SYSTEM);
    CHECK_ARGUMENT_ID(volId);
    ACQUIRE_LOCK;

    auto vol = VolumeManager::Instance()->findVolume(volId);
    if (vol == nullptr) {
        return error("Failed to find volume " + volId);
    }

    vol->setMountFlags(mountFlags);
    vol->setMountUserId(mountUserId);
    //调用VolumeBase的mount.
    int res = vol->mount();
    if ((mountFlags & MOUNT_FLAG_PRIMARY) != 0) {
        VolumeManager::Instance()->setPrimary(vol);
    }
   
    return translate(res);
}


status_t VolumeBase::mount() {
    if ((mState != State::kUnmounted) && (mState != State::kUnmountable)) {
        LOG(WARNING) << getId() << " mount requires state unmounted or unmountable";
        return -EBUSY;
    }
    //设置当前状态为checking
    setState(State::kChecking);
    //调用子类PublicVolume的doMount方法.
    status_t res = doMount();
    if (res == OK) {
        //设置挂载成功状态,向上通知onVolumeStateChanged.
        setState(State::kMounted);
    } else {
        setState(State::kUnmountable);
    }

    return res;
}

//实现挂载,doMount函数做了大量工作,由于自己水平有限,这里面很多调用还摸不清,如有大神知道,请指点指点,后续我了解了也会更新上来.
status_t PublicVolume::doMount() {
    readMetadata();
    //查看SD卡是否为vfat格式,系统是否支持.
    if (mFsType == "vfat" && vfat::IsSupported()) {
        //调用文件系统check函数检查是否是vfat格式.
        if (vfat::Check(mDevPath)) {
            LOG(ERROR) << getId() << " failed filesystem check";
            return -EIO;
        }
    } else if (mFsType == "exfat" && exfat::IsSupported()) {
        if (exfat::Check(mDevPath)) {
            LOG(ERROR) << getId() << " failed filesystem check";
            return -EIO;
        }
    } else {
        LOG(ERROR) << getId() << " unsupported filesystem " << mFsType;
        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());

    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)) {
        PLOG(ERROR) << getId() << " failed to create mount points";
        return -errno;
    }

    if (mFsType == "vfat") {
        //将设备节点挂载在mRawPath下.
        if (vfat::Mount(mDevPath, mRawPath, false, false, false, AID_MEDIA_RW, AID_MEDIA_RW, 0007,
                        true)) {
            PLOG(ERROR) << getId() << " failed to mount " << mDevPath;
            return -EIO;
        }
	
    } else if (mFsType == "exfat") {
        if (exfat::Mount(mDevPath, mRawPath, AID_MEDIA_RW, AID_MEDIA_RW, 0007)) {
            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;
    }

    if (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 FUSE mount points";
        return -errno;
    }

    dev_t before = GetDevice(mFuseWrite);

    if (!(mFusePid = fork())) {
        if (getMountFlags() & MountFlags::kPrimary) {
            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;
    }

    nsecs_t start = systemTime(SYSTEM_TIME_BOOTTIME);
    while (before == GetDevice(mFuseWrite)) {
        LOG(VERBOSE) << "Waiting for FUSE to spin up...";
        usleep(50000); // 50ms

        nsecs_t now = systemTime(SYSTEM_TIME_BOOTTIME);
        if (nanoseconds_to_milliseconds(now - start) > 5000) {
            LOG(WARNING) << "Timed out while waiting for FUSE to spin up";
            return -ETIMEDOUT;
        }
    }
    /* sdcardfs will have exited already. FUSE will still be running */
    if (TEMP_FAILURE_RETRY(waitpid(mFusePid, nullptr, WNOHANG)) == mFusePid)
        mFusePid = 0;

    return OK;
}

参考:
http://blog.csdn.net/gaugamela/article https://blog.csdn.net/Gaugamela/article/details/52484058
邓平凡大神的<深入理解Android卷1>第九章 vold的原理与机制分析

你可能感兴趣的:(Vold相关)