Android 15存储子系统深度解析(一):Vold与存储管理框架

写在前面

Android系统中的存储管理是一个复杂而精密的子系统。从SD卡的热插拔检测,到内部存储的分区挂载,再到OBB扩展文件的管理,这一切的核心都离不开一个关键的守护进程------Vold(Volume Daemon)。

作为Android存储架构的"大脑",Vold负责:

  • 🔌 设备检测: 实时监听内核Uevent,发现新插入的存储设备
  • 📦 Volume管理: 抽象和管理各类存储卷(公共存储、可采用存储、模拟存储)
  • 🔐 加密支持: 处理文件级加密(FBE)和磁盘加密
  • 🌉 跨进程通信: 通过Binder向Framework层提供存储服务

本文将基于Android 15 (AOSP 15.0) 的源码,深入剖析Vold的架构设计、启动流程、核心组件以及与StorageManagerService的交互机制。

💡 源码路径 : 本文分析的Vold源码位于 system/vold/,StorageManagerService位于 frameworks/base/services/core/java/com/android/server/StorageManagerService.java


一、Vold架构总览

1.1 Vold在Android存储架构中的位置

在Android存储架构中,Vold扮演着"承上启下"的关键角色:

如上图所示,Vold的架构可以分为五个层次:

Framework层 (Java)
  • StorageManagerService: 系统服务,提供存储管理的Java API
  • IStorageManager: AIDL接口,定义Framework层的存储服务接口
Native Binder层 (C++)
  • VoldNativeService: 实现IVold接口的Binder服务,是Vold对外提供服务的入口
  • IVold: AIDL接口,定义了从Framework到Native的跨进程调用接口
  • IVoldListener: AIDL接口,用于Vold向Framework发送事件回调
Vold核心层 (C++)
  • VolumeManager: Vold的核心管理器(单例),管理所有Disk和Volume对象
  • NetlinkManager: 负责监听内核的Netlink Uevent事件
  • NetlinkHandler: 处理Netlink事件,将设备插拔事件转换为Volume操作
存储模型层 (C++)
  • Disk: 物理磁盘的抽象(SD卡、USB存储)
  • VolumeBase : Volume的基类,提供通用的挂载/卸载接口
    • PublicVolume: 公共存储卷(FAT32/exFAT格式)
    • PrivateVolume: 可采用存储(Adoptable Storage,ext4加密)
    • EmulatedVolume: 模拟存储卷(/storage/emulated)
    • ObbVolume: OBB扩展文件卷
底层支持
  • Kernel Netlink: 内核Uevent机制,用于设备热插拔事件通知
  • /dev/block: 块设备节点
  • fstab: 文件系统表配置

1.2 核心设计模式

Vold的设计体现了多个经典的设计模式:

1. 单例模式 (Singleton)

cpp 复制代码
// system/vold/VolumeManager.h
class VolumeManager {
    static VolumeManager* sInstance;
public:
    static VolumeManager* Instance();
};

VolumeManager和NetlinkManager都采用单例模式,确保全局只有一个管理器实例。

2. 观察者模式 (Observer)

cpp 复制代码
// system/vold/VoldNativeService.h
class VoldNativeService : public BinderService<VoldNativeService>, public os::BnVold {
    binder::Status setListener(const android::sp<android::os::IVoldListener>& listener);
};

通过IVoldListener接口,StorageManagerService可以订阅Vold的事件通知。

3. 继承多态 (Inheritance)

cpp 复制代码
// system/vold/model/VolumeBase.h
class VolumeBase {
protected:
    virtual status_t doMount() = 0;
    virtual status_t doUnmount() = 0;
};

class PublicVolume : public VolumeBase { ... };
class PrivateVolume : public VolumeBase { ... };

各种Volume类型继承自VolumeBase,实现特定的挂载逻辑。


二、Vold启动流程详解

2.1 Init进程启动Vold

Vold作为一个Native守护进程,由init进程根据init.rc配置文件启动:

rc 复制代码
# system/core/rootdir/init.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

配置解析:

  • class core: Vold属于核心服务,在early-boot阶段启动
  • --*_context: 指定SELinux上下文,用于blkid和fsck工具的安全隔离
  • ioprio be 2: 设置I/O优先级为Best Effort,优先级2
  • shutdown critical: Vold崩溃会导致系统重启

2.2 main()函数:初始化流程

让我们深入到system/vold/main.cpp的启动代码:

cpp 复制代码
int main(int argc, char** argv) {
    // 1. 初始化日志系统
    setenv("ANDROID_LOG_TAGS", "*:d", 1);
    android::base::InitLogging(argv, &VoldLogger);
    LOG(INFO) << "Vold 3.0 (the awakening) firing up";

    // 2. 检测文件系统支持
    LOG(DEBUG) << "Detected support for:"
               << (android::vold::IsFilesystemSupported("ext4") ? " ext4" : "")
               << (android::vold::IsFilesystemSupported("f2fs") ? " f2fs" : "")
               << (android::vold::IsFilesystemSupported("vfat") ? " vfat" : "");

    // 3. 初始化SELinux
    sehandle = selinux_android_file_context_handle();
    if (!sehandle) {
        LOG(ERROR) << "Failed to get SELinux file contexts handle";
        exit(1);
    }
    selinux_android_set_sehandle(sehandle);

    // 4. 创建必要的目录
    mkdir("/dev/block/vold", 0755);

    // 5. 创建核心组件单例
    VolumeManager* vm = VolumeManager::Instance();
    NetlinkManager* nm = NetlinkManager::Instance();

    // 6. 启动VolumeManager
    if (vm->start()) {
        PLOG(ERROR) << "Unable to start VolumeManager";
        exit(1);
    }

    // 7. 处理fstab配置
    VoldConfigs configs = {};
    process_config(vm, &configs);

    // 8. 启动Binder服务
    android::hardware::configureRpcThreadpool(1, false);
    if (android::vold::VoldNativeService::start() != android::OK) {
        LOG(ERROR) << "Unable to start VoldNativeService";
        exit(1);
    }

    // 9. 启动NetlinkManager
    if (nm->start()) {
        PLOG(ERROR) << "Unable to start NetlinkManager";
        exit(1);
    }

    // 10. 设置系统属性
    android::base::SetProperty("vold.has_adoptable", configs.has_adoptable ? "1" : "0");
    android::base::SetProperty("vold.has_quota", configs.has_quota ? "1" : "0");

    // 11. Coldboot扫描已连接设备
    coldboot("/sys/block");

    // 12. 进入主循环
    android::IPCThreadState::self()->joinThreadPool();
    LOG(INFO) << "vold shutting down";
}

2.3 关键步骤详解

步骤1-2: 日志和文件系统检测
  • VoldLogger: 自定义日志处理器,early-boot阶段的错误会同时输出到kernel log
  • IsFilesystemSupported(): 检查内核是否支持ext4/f2fs/vfat文件系统
步骤3: SELinux初始化
cpp 复制代码
sehandle = selinux_android_file_context_handle();

获取SELinux文件上下文句柄,用于后续创建文件时设置正确的安全上下文。

步骤5: 单例创建
cpp 复制代码
VolumeManager* vm = VolumeManager::Instance();

VolumeManager采用懒加载单例模式:

cpp 复制代码
VolumeManager* VolumeManager::sInstance = nullptr;

VolumeManager* VolumeManager::Instance() {
    if (!sInstance) {
        sInstance = new VolumeManager();
    }
    return sInstance;
}
步骤7: 处理fstab配置
cpp 复制代码
static int process_config(VolumeManager* vm, VoldConfigs* configs) {
    // 读取fstab
    if (!ReadDefaultFstab(&fstab_default)) {
        PLOG(ERROR) << "Failed to open default fstab";
        return -1;
    }

    // 遍历fstab条目
    for (auto& entry : fstab_default) {
        // 检查是否支持quota/reserved/compress
        if (entry.fs_mgr_flags.quota) configs->has_quota = true;
        if (entry.reserved_size > 0) configs->has_reserved = true;
        if (entry.fs_mgr_flags.fs_compress) configs->has_compress = true;

        // 处理vold_managed标记的分区
        if (entry.fs_mgr_flags.vold_managed) {
            std::string sysPattern(entry.blk_device);
            std::string nickname(entry.label);
            int flags = 0;

            // 可采用存储标记
            if (entry.is_encryptable()) {
                flags |= android::vold::Disk::Flags::kAdoptable;
                configs->has_adoptable = true;
            }

            // 添加到VolumeManager
            vm->addDiskSource(std::shared_ptr<VolumeManager::DiskSource>(
                new VolumeManager::DiskSource(sysPattern, nickname, flags)));
        }
    }
    return 0;
}

fstab示例:

复制代码
# 可采用的SD卡
/devices/platform/soc/7864900.sdhci/mmc_host/mmc*  auto  auto  defaults  vold_managed=sdcard1:auto,encryptable=userdata
步骤11: Coldboot扫描
cpp 复制代码
static void coldboot(const char* path) {
    DIR* d = opendir(path);
    if (d) {
        do_coldboot(d, 0);
        closedir(d);
    }
}

static void do_coldboot(DIR* d, int lvl) {
    // 遍历/sys/block目录
    while ((de = readdir(d))) {
        // 向uevent节点写入"add",触发内核发送uevent事件
        fd = openat(dfd, "uevent", O_WRONLY | O_CLOEXEC);
        if (fd >= 0) {
            write(fd, "add\n", 4);
            close(fd);
        }
    }
}

Coldboot的作用是主动触发内核重新发送已连接设备的uevent事件,确保Vold启动时能发现已插入的存储设备。


三、VolumeManager核心机制

3.1 VolumeManager的数据结构

让我们看看VolumeManager如何组织和管理Disk和Volume:

cpp 复制代码
// system/vold/VolumeManager.h
class VolumeManager {
private:
    std::mutex mLock;  // 全局锁
    std::mutex mCryptLock;  // 加密操作锁

    // 核心数据结构
    std::list<std::shared_ptr<DiskSource>> mDiskSources;  // 磁盘源配置
    std::list<std::shared_ptr<android::vold::Disk>> mDisks;  // 物理磁盘列表
    std::list<std::shared_ptr<android::vold::Disk>> mPendingDisks;  // 待处理磁盘
    std::list<std::shared_ptr<android::vold::VolumeBase>> mObbVolumes;  // OBB卷
    std::list<std::shared_ptr<android::vold::VolumeBase>> mInternalEmulatedVolumes;  // 模拟卷

    // 用户管理
    std::unordered_map<userid_t, int> mAddedUsers;
    std::set<userid_t> mStartedUsers;

    // 事件监听器
    android::sp<android::os::IVoldListener> mListener;
};

3.2 Disk和Volume的关系

Disk (物理磁盘抽象):

cpp 复制代码
// system/vold/model/Disk.h
class Disk {
public:
    enum Flags {
        kAdoptable = 1 << 0,      // 可采用存储
        kDefaultPrimary = 1 << 1, // 默认主存储
        kSd = 1 << 2,             // SD卡
        kUsb = 1 << 3,            // USB存储
        kEmmc = 1 << 4,           // eMMC内部存储
    };

private:
    std::string mId;              // 唯一ID,如"disk:179:0"
    std::string mSysPath;         // sysfs路径,如"/sys/devices/.../mmcblk0"
    std::string mDevPath;         // 设备路径,如"/dev/block/mmcblk0"
    dev_t mDevice;                // 设备号(major:minor)
    uint64_t mSize;               // 磁盘大小
    std::string mLabel;           // 磁盘标签
    int mFlags;                   // 标志位
    std::vector<std::shared_ptr<VolumeBase>> mVolumes;  // 包含的Volume列表
};

VolumeBase (Volume基类):

cpp 复制代码
// system/vold/model/VolumeBase.h
class VolumeBase {
public:
    enum class Type {
        kPublic = 0,   // 公共存储
        kPrivate,      // 可采用存储
        kEmulated,     // 模拟存储
        kAsec,         // 已废弃
        kObb,          // OBB文件
        kStub,         // 存根卷
    };

    enum class State {
        kUnmounted = 0,       // 未挂载
        kChecking,            // 检查中
        kMounted,             // 已挂载
        kMountedReadOnly,     // 只读挂载
        kFormatting,          // 格式化中
        kEjecting,            // 弹出中
        kUnmountable,         // 无法挂载
        kRemoved,             // 已移除
        kBadRemoval,          // 异常移除
    };

protected:
    virtual status_t doMount() = 0;     // 子类实现挂载逻辑
    virtual status_t doUnmount() = 0;   // 子类实现卸载逻辑

private:
    std::string mId;          // Volume ID,如"public:179:1"
    std::string mDiskId;      // 所属Disk ID
    Type mType;               // Volume类型
    State mState;             // 当前状态
    std::string mPath;        // 挂载路径
};

3.3 Volume生命周期管理

创建Volume:

cpp 复制代码
// system/vold/model/Disk.cpp
void Disk::createPublicVolume(dev_t device) {
    auto vol = std::make_shared<PublicVolume>(device);
    // 设置Volume属性
    vol->setDiskId(getId());
    vol->setPartGuid(partGuid);

    // 添加到Disk的Volume列表
    mVolumes.push_back(vol);

    // 创建Volume(通知Framework)
    vol->create();
}

挂载Volume:

cpp 复制代码
// system/vold/model/VolumeBase.cpp
status_t VolumeBase::mount() {
    // 1. 状态检查
    if (mState != State::kUnmounted) {
        LOG(WARNING) << "Already mounted or mounting";
        return -EBUSY;
    }

    // 2. 设置为检查状态
    setState(State::kChecking);

    // 3. 调用子类实现的挂载逻辑
    status_t res = doMount();

    // 4. 根据结果更新状态
    if (res == OK) {
        setState(State::kMounted);
    } else {
        setState(State::kUnmountable);
    }

    return res;
}

PublicVolume的挂载实现:

cpp 复制代码
// system/vold/model/PublicVolume.cpp
status_t PublicVolume::doMount() {
    // 1. 读取文件系统类型
    std::string fsType;
    if (ReadMetadataUntrusted(mDevPath, &fsType, &fsUuid, &fsLabel)) {
        LOG(WARNING) << "Failed to read metadata";
        fsType = "auto";
    }

    // 2. 执行fsck检查
    if (fsType == "vfat" && vfat::Check(mDevPath)) {
        LOG(ERROR) << "FAT filesystem check failed";
        return -EIO;
    } else if (fsType == "exfat" && exfat::Check(mDevPath)) {
        LOG(ERROR) << "exFAT filesystem check failed";
        return -EIO;
    }

    // 3. 创建挂载点
    if (PrepareDir(mRawPath, 0700, AID_ROOT, AID_ROOT)) {
        PLOG(ERROR) << "Failed to create mount point " << mRawPath;
        return -errno;
    }

    // 4. 执行mount系统调用
    if (fsType == "vfat") {
        if (vfat::Mount(mDevPath, mRawPath, false, false, false,
                       AID_MEDIA_RW, AID_MEDIA_RW, 0007, true)) {
            PLOG(ERROR) << "Failed to mount vfat";
            return -EIO;
        }
    } else if (fsType == "exfat") {
        if (exfat::Mount(mDevPath, mRawPath, AID_MEDIA_RW, AID_MEDIA_RW, 0007)) {
            PLOG(ERROR) << "Failed to mount exfat";
            return -EIO;
        }
    }

    // 5. 设置挂载路径
    setPath(mRawPath);
    return OK;
}

四、Netlink事件处理机制

4.1 Netlink与Uevent

Linux内核通过Netlink Socket向用户空间发送设备事件(Uevent)。Vold通过NetlinkManager监听这些事件,实现设备的热插拔检测。

Uevent事件格式示例:

复制代码
ACTION=add
DEVPATH=/devices/platform/soc/7864900.sdhci/mmc_host/mmc0/mmc0:0001/block/mmcblk0
SUBSYSTEM=block
MAJOR=179
MINOR=0
DEVNAME=mmcblk0
DEVTYPE=disk

4.2 NetlinkManager实现

cpp 复制代码
// system/vold/NetlinkManager.cpp
int NetlinkManager::start() {
    // 1. 创建Netlink socket
    mSock = socket(PF_NETLINK, SOCK_DGRAM | SOCK_CLOEXEC, NETLINK_KOBJECT_UEVENT);
    if (mSock < 0) {
        PLOG(ERROR) << "Unable to create Netlink socket";
        return -1;
    }

    // 2. 绑定到KOBJECT_UEVENT组
    struct sockaddr_nl addr;
    memset(&addr, 0, sizeof(addr));
    addr.nl_family = AF_NETLINK;
    addr.nl_pid = getpid();
    addr.nl_groups = 0xFFFFFFFF;  // 接收所有组的事件

    if (bind(mSock, (struct sockaddr*)&addr, sizeof(addr)) < 0) {
        PLOG(ERROR) << "Unable to bind Netlink socket";
        close(mSock);
        return -1;
    }

    // 3. 创建NetlinkHandler并启动监听线程
    mHandler = new NetlinkHandler(mSock);
    if (mHandler->start()) {
        PLOG(ERROR) << "Unable to start NetlinkHandler";
        return -1;
    }

    return 0;
}

4.3 NetlinkHandler处理流程

cpp 复制代码
// system/vold/NetlinkHandler.cpp
void NetlinkHandler::onEvent(NetlinkEvent* evt) {
    VolumeManager* vm = VolumeManager::Instance();
    const char* subsys = evt->getSubsystem();

    // 只处理block子系统事件
    if (!subsys || strcmp(subsys, "block") != 0) {
        return;
    }

    // 根据action类型分发
    const char* action = evt->getAction();
    if (!strcmp(action, "add")) {
        // 设备添加
        vm->handleBlockEvent(evt);
    } else if (!strcmp(action, "remove")) {
        // 设备移除
        vm->handleBlockEvent(evt);
    } else if (!strcmp(action, "change")) {
        // 设备变化(如SD卡写保护开关)
        vm->handleBlockEvent(evt);
    }
}

4.4 VolumeManager处理块设备事件

cpp 复制代码
// system/vold/VolumeManager.cpp
void VolumeManager::handleBlockEvent(NetlinkEvent* evt) {
    std::lock_guard<std::mutex> lock(mLock);

    const char* devpath = evt->findParam("DEVPATH");
    const char* action = evt->getAction();

    // 解析设备号
    int major = std::stoi(evt->findParam("MAJOR"));
    int minor = std::stoi(evt->findParam("MINOR"));
    dev_t device = makedev(major, minor);

    if (!strcmp(action, "add")) {
        // 1. 检查是否匹配DiskSource
        for (const auto& source : mDiskSources) {
            if (source->matches(devpath)) {
                // 2. 创建Disk对象
                auto disk = std::make_shared<android::vold::Disk>(
                    eventPath, device, source->getNickname(), source->getFlags());

                // 3. 添加到磁盘列表
                handleDiskAdded(disk);
                break;
            }
        }
    } else if (!strcmp(action, "remove")) {
        // 移除对应的Disk
        handleDiskRemoved(device);
    }
}

void VolumeManager::handleDiskAdded(const std::shared_ptr<android::vold::Disk>& disk) {
    // 1. 添加到mDisks列表
    mDisks.push_back(disk);

    // 2. 创建Disk(读取分区表,创建Volume)
    disk->create();

    // 3. 通知Framework
    notifyEvent(ResponseCode::DiskCreated,
                StringPrintf("%d", disk->getId()));
}

五、Binder通信:Framework与Vold的桥梁

5.1 VoldNativeService架构

VoldNativeService是Vold对外提供服务的Binder接口实现:

cpp 复制代码
// system/vold/VoldNativeService.h
class VoldNativeService : public BinderService<VoldNativeService>,
                          public os::BnVold {
public:
    static status_t start();
    static char const* getServiceName() { return "vold"; }

    // Listener管理
    binder::Status setListener(const android::sp<android::os::IVoldListener>& listener);

    // Volume操作
    binder::Status mount(const std::string& volId, int32_t mountFlags, int32_t mountUserId,
                         const android::sp<android::os::IVoldMountCallback>& callback);
    binder::Status unmount(const std::string& volId);
    binder::Status format(const std::string& volId, const std::string& fsType);

    // Disk操作
    binder::Status partition(const std::string& diskId, int32_t partitionType, int32_t ratio);
    binder::Status forgetPartition(const std::string& partGuid, const std::string& fsUuid);

    // 用户管理
    binder::Status onUserAdded(int32_t userId, int32_t userSerial, int32_t sharesStorageWithUserId);
    binder::Status onUserRemoved(int32_t userId);
    binder::Status onUserStarted(int32_t userId);
    binder::Status onUserStopped(int32_t userId);

    // FBE加密
    binder::Status createUserStorageKeys(int32_t userId, bool ephemeral);
    binder::Status destroyUserStorageKeys(int32_t userId);
    binder::Status unlockCeStorage(int32_t userId, const std::vector<uint8_t>& secret);
    binder::Status lockCeStorage(int32_t userId);

    // OBB管理
    binder::Status createObb(const std::string& sourcePath, int32_t ownerGid,
                             std::string* _aidl_return);
    binder::Status destroyObb(const std::string& volId);

    // 存储维护
    binder::Status fstrim(int32_t fstrimFlags,
                          const android::sp<android::os::IVoldTaskListener>& listener);
};

5.2 StorageManagerService与Vold的交互

完整的SD卡挂载流程:

阶段1: 设备检测(内核→Vold→Framework)
java 复制代码
// frameworks/base/services/core/java/com/android/server/StorageManagerService.java
private final IVoldListener mListener = new IVoldListener.Stub() {
    @Override
    public void onDiskCreated(String diskId, int flags) {
        // 1. 接收Vold通知:发现新磁盘
        synchronized (mLock) {
            final DiskInfo disk = new DiskInfo(diskId, flags);
            mDisks.put(diskId, disk);
        }
        // 2. 通知监听器
        mHandler.obtainMessage(H_DISK_SCANNED, disk).sendToTarget();
    }

    @Override
    public void onVolumeCreated(String volId, int type, String diskId, String partGuid) {
        // 3. 接收Vold通知:发现新Volume
        synchronized (mLock) {
            final VolumeInfo vol = new VolumeInfo(volId, type, disk, partGuid);
            mVolumes.put(volId, vol);
        }
        // 4. 发送广播通知应用
        mHandler.obtainMessage(H_VOLUME_STATE_CHANGED, vol).sendToTarget();
    }
};
阶段2: 挂载请求(Framework→Vold)
java 复制代码
// StorageManagerService.java
@Override
public void mount(String volId) {
    // 1. 权限检查
    enforcePermission(android.Manifest.permission.MOUNT_UNMOUNT_FILESYSTEMS);

    // 2. 查找Volume
    final VolumeInfo vol = findVolumeByIdOrThrow(volId);
    if (vol.type == VolumeInfo.TYPE_PRIVATE || vol.type == VolumeInfo.TYPE_PUBLIC) {
        // 3. 调用Vold挂载
        try {
            mVold.mount(vol.id, vol.mountFlags, vol.mountUserId,
                       new IVoldMountCallback.Stub() {
                @Override
                public void onStatus(int status, PersistableBundle extras) {
                    // 挂载进度回调
                }
            });
        } catch (Exception e) {
            Slog.wtf(TAG, e);
        }
    }
}

VoldNativeService处理挂载请求:

cpp 复制代码
// system/vold/VoldNativeService.cpp
binder::Status VoldNativeService::mount(const std::string& volId, int32_t mountFlags,
                                        int32_t mountUserId,
                                        const sp<IVoldMountCallback>& callback) {
    ENFORCE_SYSTEM_OR_ROOT;

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

    // 2. 设置挂载参数
    vol->setMountFlags(mountFlags);
    vol->setMountUserId(mountUserId);
    vol->setMountCallback(callback);

    // 3. 执行挂载
    int res = vol->mount();
    if (res != OK) {
        return error("Failed to mount " + volId);
    }

    return ok();
}

5.3 事件通知机制

Vold通过IVoldListener向Framework发送异步事件:

cpp 复制代码
// system/vold/VoldNativeService.cpp
void VoldNativeService::notifyDiskScanned(const std::string& diskId, int flags) {
    auto listener = VolumeManager::Instance()->getListener();
    if (listener) {
        listener->onDiskScanned(diskId, flags);
    }
}

void VoldNativeService::notifyVolumeStateChanged(const std::string& volId, int state) {
    auto listener = VolumeManager::Instance()->getListener();
    if (listener) {
        listener->onVolumeStateChanged(volId, state);
    }
}

六、实战:Vold调试技巧

6.1 查看Vold日志

bash 复制代码
# 1. 实时查看Vold日志
adb logcat -s vold:*

# 2. 查看Vold错误日志
adb logcat -s vold:E

# 3. 查看特定Volume的日志
adb logcat | grep "public:179:1"

6.2 使用dumpsys分析存储状态

bash 复制代码
# 1. 查看所有存储信息
adb shell dumpsys mount

# 2. 查看Disk列表
adb shell dumpsys mount | grep "Disk:"

# 3. 查看Volume列表
adb shell dumpsys mount | grep "Volume:"

dumpsys输出示例:

复制代码
Disks:
  disk:179:0 (SD卡):
    flags=kSd|kAdoptable
    size=31914983424
    sysPath=/sys/devices/.../mmcblk0
    devPath=/dev/block/mmcblk0
    nickname=sdcard1
    volumes:
      public:179:1

Volumes:
  public:179:1 (SD卡):
    type=kPublic
    diskId=disk:179:0
    partGuid=00000000-0000-0000-0000-000000000000
    state=kMounted
    path=/storage/0000-0000
    internalPath=/mnt/media_rw/0000-0000
    fsType=vfat
    fsUuid=0000-0000
    fsLabel=SD Card

6.3 手动触发Vold操作

bash 复制代码
# 1. 通过vdc(Vold Direct Command)手动挂载Volume
adb shell vdc volume mount public:179:1

# 2. 卸载Volume
adb shell vdc volume unmount public:179:1

# 3. 格式化Volume
adb shell vdc volume format public:179:1 auto

# 4. 分区Disk
adb shell vdc volume partition disk:179:0 public

# 5. 创建OBB Volume
adb shell vdc volume mkobb /data/app/com.example/expansion.obb 1000

6.4 分析Netlink事件

bash 复制代码
# 1. 监听内核Uevent
adb shell getevent -l /sys/kernel/uevent

# 2. 手动触发coldboot
adb shell "echo add > /sys/block/mmcblk0/uevent"

# 3. 查看设备树
adb shell ls -R /sys/devices/platform/*/mmc_host

6.5 使用Systrace分析存储性能

bash 复制代码
# 追踪Vold的挂载流程
systrace.py -t 10 -o trace.html sched freq idle am wm gfx view binder_driver \
            hal dalvik disk pm ss database package_manager vold

# 在Chrome中打开trace.html,搜索"vold"或"mount"关键字

七、Android 15的Vold新特性

7.1 增强的Adoptable Storage

Android 15对可采用存储进行了优化:

  • 更快的格式化速度 : 使用mkfs.ext4 -E lazy_itable_init,lazy_journal_init
  • 更好的性能 : 默认启用discardnoatime挂载选项

7.2 改进的FBE(File-Based Encryption)

cpp 复制代码
// Android 15新增的FBE API
binder::Status VoldNativeService::setCeStorageProtection(int32_t userId,
                                                          const std::vector<uint8_t>& secret) {
    // 支持动态修改CE(Credential Encrypted)存储的保护密钥
    return translate(fscrypt_set_ce_key_protection(userId, secret));
}

7.3 FUSE Passthrough优化

Android 15引入了FUSE Passthrough机制,减少FUSE带来的性能开销:

cpp 复制代码
// 启用FUSE Passthrough
if (android::base::GetBoolProperty("persist.sys.fuse.passthrough.enable", false)) {
    vol->enablePassthrough();
}

八、常见问题与解决方案

Q1: SD卡插入后无法识别

排查步骤:

  1. 检查Vold日志是否收到uevent事件:

    bash 复制代码
    adb logcat -s vold:D | grep "handleBlockEvent"
  2. 检查fstab是否配置了vold_managed:

    bash 复制代码
    adb shell cat /vendor/etc/fstab* | grep vold_managed
  3. 检查SELinux权限:

    bash 复制代码
    adb shell getenforce  # 应该是Enforcing
    adb logcat | grep "avc.*denied.*vold"

Q2: Volume挂载失败

常见原因:

  • 文件系统损坏:运行fsck检查
  • SELinux上下文错误:检查/mnt/media_rw的安全上下文
  • 权限不足:确保Vold运行在root权限

解决方案:

bash 复制代码
# 1. 强制fsck检查
adb shell vdc volume fsck public:179:1

# 2. 重新格式化
adb shell vdc volume format public:179:1 vfat

# 3. 重启Vold
adb shell stop vold && adb shell start vold

Q3: Adoptable Storage性能差

优化建议:

  1. 使用高速SD卡(UHS-I Class 10以上)

  2. 启用TRIM支持:

    bash 复制代码
    adb shell sm set-force-adoptable true
  3. 定期运行fstrim:

    bash 复制代码
    adb shell sm fstrim

总结

本文深入剖析了Android 15的Vold存储管理框架,涵盖了以下核心内容:

  1. 架构设计: Vold采用分层架构,通过VolumeManager、NetlinkManager等核心组件实现存储管理
  2. 启动流程: 从init进程启动到Binder服务就绪的完整流程
  3. Volume管理: Disk和Volume的组织关系,以及Volume的生命周期状态机
  4. 事件处理: 基于Netlink的设备热插拔检测机制
  5. Binder通信: VoldNativeService与StorageManagerService的跨进程交互
  6. 调试技巧: 使用logcat、dumpsys、vdc等工具分析存储问题

Vold作为Android存储架构的核心,其设计体现了单一职责分层解耦事件驱动等优秀的软件工程思想。理解Vold的工作原理,对于进行存储相关的系统开发和问题排查至关重要。

在下一篇文章中,我们将深入探讨FUSE文件系统与Scoped Storage机制,分析MediaProvider如何通过FUSE实现应用的存储隔离和权限控制。


参考资料


系列文章


欢迎来我中的个人主页找到更多有用的知识和有趣的产品

相关推荐
得一录2 小时前
Android 方向控制控件
android
久思无邪2 小时前
森氧沐歌装配式车载制氧机:政策东风下,重构车载呼吸新生态
重构·车载系统
美狐美颜SDK开放平台2 小时前
跨平台开发实战:直播美颜sdk动态贴纸在 Android / iOS / HarmonyOS 的落地方案
android·ios·harmonyos·美颜sdk·直播美颜sdk·视频美颜sdk·美颜api
2501_916008892 小时前
在不越狱前提下导出 iOS 应用文件的过程,访问应用沙盒目录,获取真实数据
android·macos·ios·小程序·uni-app·cocoa·iphone
2501_915106322 小时前
Android和IOS 移动应用App图标生成与使用 Assets.car生成
android·ios·小程序·https·uni-app·iphone·webview
灵感菇_3 小时前
深入解析 Android事件分发机制
android·ui
TheNextByte13 小时前
如何在Mac上获取Android消息
android·macos
_李小白3 小时前
【Android 美颜相机】第十二天:GPUImageFilterGroup 源码解析
android·数码相机
_李小白3 小时前
【Android GLSurfaceView源码学习】第三天:GLSurfaceView的Surface、GLES与EGLSurface的关联
android·学习