Vold功能实现

相关文件

system/vold/main.cpp
system/vold/CommandListener.cpp
system/vold/DirectVolume.cpp
system/vold/NetlinkManager.cpp
system/vold/NetlinkHandler.cpp
system/vold/Volume.cpp
system/vold/VolumeManager.cpp

主流程解析

int main() {
    ......
    // 创建VolumeManager单例对象
    if (!(vm = VolumeManager::Instance())) {
        exit(1);
    };

    // 创建NetlinkManager单例对象
    if (!(nm = NetlinkManager::Instance())) {
        exit(1);
    };

    // 创建CommandListener
    cl = new CommandListener();
    vm->setBroadcaster((SocketListener *) cl);
    nm->setBroadcaster((SocketListener *) cl);

    if (vm->start()) {
        exit(1);
    }

    // 解析vold.fstab配置文件
    if (process_config(vm)) {
    }

    // 监听内核的消息
    if (nm->start()) {
        exit(1);
    }

    // 通知内核上报uevent事件
    coldboot("/sys/block");

    // 监听framework层的消息
    if (cl->startListener()) {
        exit(1);
    }

    while(1) {
        sleep(1000);
    }

    exit(0);
}

模块分类

挂载点及其管理

socket连接及其管理

命令抽象

内核事件抽象

要点解析

接收framework指令

CommandListener::CommandListener

CommandListener::CommandListener() :
                 FrameworkListener("vold") {
    registerCmd(new DumpCmd());
    registerCmd(new VolumeCmd());
    registerCmd(new AsecCmd());
    registerCmd(new ObbCmd());
    registerCmd(new ShareCmd());
    registerCmd(new StorageCmd());
    registerCmd(new XwarpCmd());
}

SocketListener::startListener

int SocketListener::startListener() {
    if (pthread_create(&mThread, NULL, SocketListener::threadStart, this)) {
        return -1;
    }

    return 0;
}
void *SocketListener::threadStart(void *obj) {
    SocketListener *me = reinterpret_cast<SocketListener *>(obj);

    me->runListener();
    pthread_exit(NULL);
    return NULL;
}

SocketListener::runListener

void SocketListener::runListener() {
    ......
    while(1) {
        ...... 
        do {
            for (it = mClients->begin(); it != mClients->end(); ++it) {
                if (FD_ISSET(fd, &read_fds)) {
                    // 调用FrameworkListener::onDataAvailable()
                    if (!onDataAvailable(*it)) {
                        ...... 
                    }
                    ......
                }
            }
        } while (0);
    }
}

FrameworkListener::onDataAvailable

bool FrameworkListener::onDataAvailable(SocketClient *c) {
    ......
    if ((len = read(c->getSocket(), buffer, sizeof(buffer) -1)) < 0) {
        return false;
    } else if (!len)
        return false;

    ......
    for (i = 0; i < len; i++) {
        if (buffer[i] == '\0') {
            dispatchCommand(c, buffer + offset);
            offset = i + 1;
        }
    }
    return true;
}

FrameworkListener::dispatchCommand

void FrameworkListener::dispatchCommand(SocketClient *cli, char *data) {
    ......    
    for (i = mCommands->begin(); i != mCommands->end(); ++i) {
        ......
        if (!strcmp(argv[0], c->getCommand())) {
            if (c->runCommand(cli, argc, argv)) {
            }
            goto out;
        }
    }
    ......
}

CommandListener::VolumeCmd::runCommand

int CommandListener::VolumeCmd::runCommand(SocketClient *cli,
                                           int argc, char **argv) {
    dumpArgs(argc, argv, -1);

    if (argc < 2) {
        cli->sendMsg(ResponseCode::CommandSyntaxError, "Missing Argument", false);
        return 0;
    }

    VolumeManager *vm = VolumeManager::Instance();
    int rc = 0;

    if (!strcmp(argv[1], "list")) {
        return vm->listVolumes(cli);
    } else if (!strcmp(argv[1], "mount")) {
        if (argc != 3) {
            cli->sendMsg(ResponseCode::CommandSyntaxError, "Usage: volume mount <path>", false);
            return 0;
        }
        rc = vm->mountVolume(argv[2]);
    } else if (!strcmp(argv[1], "unmount")) {
        if (argc < 3 || argc > 4 || (argc == 4 && strcmp(argv[3], "force"))) {
            cli->sendMsg(ResponseCode::CommandSyntaxError, "Usage: volume unmount <path> [force]", false);
            return 0;
        }

        bool force = false;
        if (argc >= 4 && !strcmp(argv[3], "force")) {
            force = true;
        }
        rc = vm->unmountVolume(argv[2], force);
    } else {
        cli->sendMsg(ResponseCode::CommandSyntaxError, "Unknown volume cmd", false);
    }

    if (!rc) {
        cli->sendMsg(ResponseCode::CommandOkay, "volume operation succeeded", false);
    } else {
        int erno = errno;
        rc = ResponseCode::convertFromErrno();
        cli->sendMsg(rc, "volume operation failed", true);
    }

    return 0;
}

接收和上报内核事件

NetlinkManager::start

int NetlinkManager::start() {
    ......
    if ((mSock = socket(PF_NETLINK,
                        SOCK_DGRAM,NETLINK_KOBJECT_UEVENT)) < 0) {
        return -1;
    }

    if (setsockopt(mSock, SOL_SOCKET, SO_RCVBUFFORCE, &sz, sizeof(sz)) < 0) {
        return -1;
    }

    if (setsockopt(mSock, SOL_SOCKET, SO_PASSCRED, &on, sizeof(on)) < 0) {
        return -1;
    }

    if (bind(mSock, (struct sockaddr *) &nladdr, sizeof(nladdr)) < 0) {
        return -1;
    }

    mHandler = new NetlinkHandler(mSock);
    if (mHandler->start()) {
        return -1;
    }
    return 0;
}

NetlinkHandler::start

int NetlinkHandler::start() {
    // 这里调用基类SocketListener::startListener()
    return this->startListener();
}

NetlinkListener::onDataAvailable

bool NetlinkListener::onDataAvailable(SocketClient *cli)
{
    ......
    NetlinkEvent *evt = new NetlinkEvent();
    if (!evt->decode(mBuffer, count)) {
        goto out;
    }

    onEvent(evt);
out:
    delete evt;
    return true;
}

NetlinkEvent::decode

add@/devices/platform/msm_sdcc.2/mmc_host/mmc1/mmc1:c9f2/block/mmcblk0
ACTION=add
DEVPATH=/devices/platform/msm_sdcc.2/mmc_host/mmc1/mmc1:c9f2/block/mmcblk0
SUBSYSTEM=block
MAJOR=179
MINOR=0
DEVNAME=mmcblk0
DEVTYPE=disk
NPARTS=3
SEQNUM=1357
bool NetlinkEvent::decode(char *buffer, int size) {
    ......
    while (s < end) {
        if (first) {
            ......
        } else {
            if (!strncmp(s, "ACTION=", strlen("ACTION="))) {
                char *a = s + strlen("ACTION=");
                if (!strcmp(a, "add"))
                    mAction = NlActionAdd;
                else if (!strcmp(a, "remove"))
                    mAction = NlActionRemove;
                else if (!strcmp(a, "change"))
                    mAction = NlActionChange;
            } else if (!strncmp(s, "SEQNUM=", strlen("SEQNUM=")))
                mSeq = atoi(s + strlen("SEQNUM="));
            else if (!strncmp(s, "SUBSYSTEM=", strlen("SUBSYSTEM=")))
                mSubsystem = strdup(s + strlen("SUBSYSTEM="));
            else
                mParams[param_idx++] = strdup(s);
        }
        s+= strlen(s) + 1;
    }
    return true;
}

NetlinkHandler::onEvent

void NetlinkHandler::onEvent(NetlinkEvent *evt) {
    VolumeManager *vm = VolumeManager::Instance();
    const char *subsys = evt->getSubsystem();

    if (!subsys) {
        return;
    }

    if (!strcmp(subsys, "block")) {
        vm->handleBlockEvent(evt);
    } else if (!strcmp(subsys, "switch")) {
        vm->handleSwitchEvent(evt);
    } else if (!strcmp(subsys, "usb_composite")) {
        vm->handleUsbCompositeEvent(evt);
    } else if (!strcmp(subsys, "battery")) {
    } else if (!strcmp(subsys, "power_supply")) {
    }
}

VolumeManager::handleBlockEvent

void VolumeManager::handleBlockEvent(NetlinkEvent *evt) {
    ......
    for (it = mVolumes->begin(); it != mVolumes->end(); ++it) {
        if (!(*it)->handleBlockEvent(evt)) {
            hit = true;
            break;
        }
    }
    ...... 
}

VolumeManager::handleSwitchEvent

void VolumeManager::handleSwitchEvent(NetlinkEvent *evt) {
    ......
    if (!strcmp(name, "usb_configuration")) {
        mUsbConnected = !strcmp(state, "1");
        bool newAvailable = massStorageAvailable();
        if (newAvailable != oldAvailable) {
            notifyUmsAvailable(newAvailable);
        }
	} else if (!strcmp(name, "sim_card_socket")) {
        mSIMCardConnected = !strncmp(state, "closed", 6);
        bool simcard_newAvailable = SIMCardAvailable();
        if (simcard_newAvailable != simcard_oldAvailable) {
            notifySIMCardAvailable(simcard_newAvailable);
        }
    } else {
    }
}

VolumeManager::handleUsbCompositeEvent

void VolumeManager::handleUsbCompositeEvent(NetlinkEvent *evt) {
    const char *function = evt->findParam("FUNCTION");
    const char *enabled = evt->findParam("ENABLED");

    if (!function || !enabled) {
        return;
    }

    if (!strcmp(function, "usb_mass_storage")) {
        bool oldAvailable = massStorageAvailable();
        mUsbMassStorageEnabled = !strcmp(enabled, "1");
        bool newAvailable = massStorageAvailable();
        if (newAvailable != oldAvailable) {
            notifyUmsAvailable(newAvailable);
        }
    }
}

VolumeManager::notifyUmsAvailable

void VolumeManager::notifyUmsAvailable(bool available) {
    char msg[255];
    snprintf(msg, sizeof(msg), "Share method ums now %s",
             (available ? "available" : "unavailable"));
    getBroadcaster()->sendBroadcast(ResponseCode::ShareAvailabilityChange,
                                    msg, false);
}

VolumeManager::notifySIMCardAvailable

void VolumeManager::notifySIMCardAvailable(bool available) {
    char msg[255];
    snprintf(msg, sizeof(msg), "Share method ums now %s",
             (available ? "available" : "unavailable"));
    getBroadcaster()->sendBroadcast(ResponseCode::SIMCardStatChange,
                                    msg, false);
}

DirectVolume::handleBlockEvent

int DirectVolume::handleBlockEvent(NetlinkEvent *evt) {
    ......
    for (it = mPaths->begin(); it != mPaths->end(); ++it) {
        if (!strncmp(dp, *it, strlen(*it))) {
            int action = evt->getAction();
            const char *devtype = evt->findParam("DEVTYPE");

            if (action == NetlinkEvent::NlActionAdd) {
                int major = atoi(evt->findParam("MAJOR"));
                int minor = atoi(evt->findParam("MINOR"));
                char nodepath[255];

                // 动态创建磁盘的设备节点
                if (createDeviceNode(nodepath, major, minor)) {
                }
                if (!strcmp(devtype, "disk")) {
                    // 添加设备的处理
                    handleDiskAdded(dp, evt);
                } else {
                    // 添加分区的处理
                    handlePartitionAdded(dp, evt);
                }
            } else if (action == NetlinkEvent::NlActionRemove) {
                if (!strcmp(devtype, "disk")) {
                    // 移除设备的处理
                    handleDiskRemoved(dp, evt);
                } else {
                    // 移除分区的处理
                    handlePartitionRemoved(dp, evt);
                }
            } else if (action == NetlinkEvent::NlActionChange) {
                if (!strcmp(devtype, "disk")) {
                    // 设备变更的处理
                    handleDiskChanged(dp, evt);
                } else {
                    // 分区变更的处理
                    handlePartitionChanged(dp, evt);
                }
            } else {
            }
            ......
        }
    }
    ......
}

如何向Framework发送消息

SocketListener::sendBroadcast

// code:消息代码
// msg:字符串信息
// addError:是否加入错误
void SocketListener::sendBroadcast(int code, const char *msg, bool addErrno) {
    pthread_mutex_lock(&mClientsLock);
    SocketClientCollection::iterator i;

    for (i = mClients->begin(); i != mClients->end(); ++i) {
        if ((*i)->sendMsg(code, msg, addErrno)) {
        }
    }
    pthread_mutex_unlock(&mClientsLock);
}

// 调用示例如下
// getBroadcaster()->sendBroadcast(ResponseCode::ShareAvailabilityChange, msg, false);

ResponseCode

class ResponseCode {
public:
    // 100 series - Requestion action was initiated; expect another reply
    // before proceeding with a new command.
    static const int ActionInitiated            = 100;

    static const int VolumeListResult           = 110;
    static const int AsecListResult             = 111;
    static const int StorageUsersListResult     = 112;

    // 200 series - Requested action has been successfully completed
    static const int CommandOkay                = 200;
    static const int ShareStatusResult          = 210;
    static const int AsecPathResult             = 211;
    static const int ShareEnabledResult         = 212;
    static const int XwarpStatusResult          = 213;

    // 400 series - The command was accepted but the requested action
    // did not take place.
    static const int OperationFailed            = 400;
    static const int OpFailedNoMedia            = 401;
    static const int OpFailedMediaBlank         = 402;
    static const int OpFailedMediaCorrupt       = 403;
    static const int OpFailedVolNotMounted      = 404;
    static const int OpFailedStorageBusy        = 405;
    static const int OpFailedStorageNotFound    = 406;

    // 500 series - The command was not accepted and the requested
    // action did not take place.
    static const int CommandSyntaxError = 500;
    static const int CommandParameterError = 501;

    // 600 series - Unsolicited broadcasts
    static const int UnsolicitedInformational   = 600;
    static const int VolumeStateChange          = 605;
    static const int VolumeMountFailedBlank     = 610;
    static const int VolumeMountFailedDamaged   = 611;
    static const int VolumeMountFailedNoMedia   = 612;

    static const int ShareAvailabilityChange    = 620;

    static const int VolumeDiskInserted         = 630;
    static const int VolumeDiskRemoved          = 631;
    static const int VolumeBadRemoval           = 632;

    static int convertFromErrno();
};

上报消息的通信协议

磁盘操作的通信协议

字符串消息 协议代码 描述 实现方法
Share method ums now <available / unavailable> ResponseCode::ShareAvailabilityChange 通知Host端U盘模式是否可用 VolumeManager::notifyUmsAvailable
Volume <label> <mount point> disk inserted (<major>:<minor>) ResponseCode::VolumeDiskInserted 通知Framework加入新的磁盘 DirectVolume::handleDiskAdded
Volume <label> <mount point> disk inserted (<major>:<minor>) ResponseCode::VolumeDiskInserted 通知Framework加入新的分区 DirectVolume::handlePartitionAdded
Volume <label> <mount point> disk removed (<major>:<minor>) ResponseCode::VolumeDiskRemoved 通知Framework移除磁盘 DirectVolume::handleDiskRemoved
Volume <label> <mount point> disk removed (<major>:<minor>) ResponseCode::VolumeDiskRemoved 通知Framework移除分区 DirectVolume::handlePartitionRemoved
Volume <label> <mount point> disk changed (<major>:<minor>)   通知Framework磁盘状态变化 DirectVolume::handleDiskChanged
Volume <label> <mount point> disk changed (<major>:<minor>)   通知Framework分区状态变化 DirectVolume::handlePartitionChanged

状态变更的通信协议

void Volume::setState(int state) {
    char msg[255];
    int oldState = mState;

    if (oldState == state) {
        return;
    }

    mState = state;

    snprintf(msg, sizeof(msg),
             "Volume %s %s state changed from %d (%s) to %d (%s)", getLabel(),
             getMountpoint(), oldState, stateToStr(oldState), mState,
             stateToStr(mState));

    mVm->getBroadcaster()->sendBroadcast(ResponseCode::VolumeStateChange,
                                         msg, false);
}
static const char *stateToStr(int state) {
    if (state == Volume::State_Init)
        return "Initializing";
    else if (state == Volume::State_NoMedia)
        return "No-Media";
    else if (state == Volume::State_Idle)
        return "Idle-Unmounted";
    else if (state == Volume::State_Pending)
        return "Pending";
    else if (state == Volume::State_Mounted)
        return "Mounted";
    else if (state == Volume::State_Unmounting)
        return "Unmounting";
    else if (state == Volume::State_Checking)
        return "Checking";
    else if (state == Volume::State_Formatting)
        return "Formatting";
    else if (state == Volume::State_Shared)
        return "Shared-Unmounted";
    else if (state == Volume::State_SharedMnt)
        return "Shared-Mounted";
    else
        return "Unknown-Error";
}