logcat -s Vold MountService DirectVolume
虚拟SD卡相关:
一、启动过程分析
1.应用程序API
frameworks/base/core/java/android/os/storage/StorageManager.java
2.MountService
frameworks/base/services/core/java/com/android/server/MountService.java
frameworks/base/services/core/java/com/android/server/storage/
public MountService(Context context) {
mConnector = new NativeDaemonConnector(this, "vold", MAX_CONTAINERS * 2, VOLD_TAG, 25,
null); //vold的socket,与CommandListener通信
}
3.vold进程
system/vold/main.cpp
int main() {
VolumeManager *vm; //管理挂载
CommandListener *cl; //与Android的MountService通信
NetlinkManager *nm; //与Linux的Kernel通信
cl = new CommandListener();
vm->setBroadcaster((SocketListener *) cl); //VolumeManager可以与MountService通信
nm->setBroadcaster((SocketListener *) cl); //NetlinkManager可以与MountService通信
}
二、U盘挂载分析
1.vold进程获取内核U盘接入事件
system/core/libsysutils/src/SocketListener.cpp
void SocketListener::runListener() {
if (!onDataAvailable(c)) {
release(c, false);
}
}
/*
system/core/include/sysutils/NetlinkListener.h
class NetlinkListener : public SocketListener {
}
*/
system/core/libsysutils/src/NetlinkListener.cpp
bool NetlinkListener::onDataAvailable(SocketClient *cli)
{
int socket = cli->getSocket();
NetlinkEvent *evt = new NetlinkEvent();
if (evt->decode(mBuffer, count, mFormat)) {
onEvent(evt);
} else if (mFormat != NETLINK_FORMAT_BINARY) {
// Don't complain if parseBinaryNetlinkMessage returns false. That can
// just mean that the buffer contained no messages we're interested in.
SLOGE("Error decoding NetlinkEvent");
}
}
/*
system/vold/NetlinkHandler.h
class NetlinkHandler: public NetlinkListener {
}
*/
system/vold/NetlinkHandler.cpp
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);
}else if(!strcmp(subsys, "usb")) {
vm->handleHidEvent(evt);
}
}
system/vold/VolumeManager.cpp
void VolumeManager::handleBlockEvent(NetlinkEvent *evt) {
for (it = mVolumes->begin(); it != mVolumes->end(); ++it) {
(*it)->handleBlockEvent(evt);
}
volume = new DirectVolume(this, &rec, flags);
addVolume(volume);
if ( volume->handleBlockEvent(evt) !=0 ) {
SLOGD("New add volume fail to handle the event of %s",devpath);
}
}
2.向Android的MountServer发送U盘接入消息
system/vold/DirectVolume.cpp
int DirectVolume::handleBlockEvent(NetlinkEvent *evt) {
handleDiskAdded(dp, evt);
}
void DirectVolume::handleDiskAdded(const char * /*devpath*/,
NetlinkEvent *evt) {
mVm->getBroadcaster()->sendBroadcast(ResponseCode::VolumeDiskInserted,
msg, false);
}
/*
system/vold/DirectVolume.h
class DirectVolume : public Volume {
VolumeManager *mVm;
}
*/
system/vold/VolumeManager.h
class VolumeManager {
void setBroadcaster(SocketListener *sl) { mBroadcaster = sl; }
/*
system/vold/main.cpp
int main() {
VolumeManager *vm;
CommandListener *cl;
NetlinkManager *nm;
cl = new CommandListener();
vm->setBroadcaster((SocketListener *) cl);
nm->setBroadcaster((SocketListener *) cl);
}
*/
SocketListener *getBroadcaster() { return mBroadcaster; }
}
system/vold/CommandListener.h
class CommandListener : public FrameworkListener {
}
/*
system/core/include/sysutils/FrameworkListener.h
class FrameworkListener : public SocketListener {
}
*/
system/core/libsysutils/src/SocketListener.cpp
void SocketListener::sendBroadcast(int code, const char *msg, bool addErrno) {
if (c->sendMsg(code, msg, addErrno, false)) {
SLOGW("Error sending broadcast (%s)", strerror(errno));
}
}
3.Android的MountServer接收到VolumeDiskInserted消息后处理
frameworks/base/services/core/java/com/android/server/MountService.java
public boolean onEvent(int code, String raw, String[] cooked) {
if ((rc = doMountVolume(path)) != StorageResultCode.OperationSucceeded) {
Slog.w(TAG, String.format("Insertion mount failed (%d)", rc));
}
}
private int doMountVolume(String path) {
mConnector.execute("volume", "mount", path);
/*
mConnector = new NativeDaemonConnector(this, "vold", MAX_CONTAINERS * 2, VOLD_TAG, 25,
null);
*/
}
frameworks/base/services/core/java/com/android/server/NativeDaemonConnector.java
public NativeDaemonEvent execute(String cmd, Object... args)
throws NativeDaemonConnectorException {
final NativeDaemonEvent[] events = executeForList(cmd, args);
}
public NativeDaemonEvent[] executeForList(String cmd, Object... args)
throws NativeDaemonConnectorException {
return execute(DEFAULT_TIMEOUT, cmd, args);
}
public NativeDaemonEvent[] execute(int timeout, String cmd, Object... args)
throws NativeDaemonConnectorException {
NativeDaemonEvent event = null;
events.add(event);
}
public void add(int cmdNum, NativeDaemonEvent response) {
found = new PendingCmd(cmdNum, null);
mPendingCmds.add(found);
}
4.vold进程接收Android的MountServer进程的volume的mount命令
system/core/libsysutils/src/SocketListener.cpp
void SocketListener::runListener() {
if (!onDataAvailable(c)) {
release(c, false);
}
}
system/core/libsysutils/src/FrameworkListener.cpp
bool FrameworkListener::onDataAvailable(SocketClient *c) {
dispatchCommand(c, buffer + offset);
}
void FrameworkListener::dispatchCommand(SocketClient *cli, char *data) {
for (i = mCommands->begin(); i != mCommands->end(); ++i) {
FrameworkCommand *c = *i;
/*
void FrameworkListener::registerCmd(FrameworkCommand *cmd) {
mCommands->push_back(cmd);
}
system/core/include/sysutils/FrameworkListener.h
class FrameworkListener : public SocketListener {
}
system/vold/CommandListener.h
class CommandListener : public FrameworkListener {
}
system/vold/CommandListener.cpp
CommandListener::CommandListener() :
FrameworkListener("vold", true) {
registerCmd(new DumpCmd());
registerCmd(new VolumeCmd()); //volume的mount命令
registerCmd(new AsecCmd());
registerCmd(new ObbCmd());
}
*/
if (c->runCommand(cli, argc, argv)) {
SLOGW("Handler '%s' error (%s)", c->getCommand(), strerror(errno));
}
}
}
system/vold/CommandListener.cpp
int CommandListener::VolumeCmd::runCommand(SocketClient *cli,
int argc, char **argv) {
VolumeManager *vm = VolumeManager::Instance();
else if (!strcmp(argv[1], "mount")) {
rc = vm->mountVolume(argv[2]);
}
}
system/vold/VolumeManager.cpp
int VolumeManager::mountVolume(const char *label) {
Volume *v = lookupVolume(label);
return v->mountVol();
}
/system/vold/Volume.cpp
int Volume::mountVol() {
if (isNtfsFS) {
if (Ntfs::doMount(devicePath, getMountpoint(), false, false, AID_MEDIA_RW, AID_MEDIA_RW, permMask)) { //实际调用Linux系统调用挂载
SLOGE("%s failed to mount via NTFS (%s)\n", devicePath, strerror(errno));
isNtfsFS = false;
} else {
isFatFs = false;
isExtFs = false;
isExfatFs = false;
}
}
setState(Volume::State_Mounted);
}
void Volume::setState(int state) {
mVm->getBroadcaster()->sendBroadcast(ResponseCode::VolumeStateChange,
msg, false); //同之前消息发送,不做分析;MountServer会收到VolumeStateChange消息
}
5.Android的MountServer收到VolumeStateChange消息通知应用
frameworks/base/services/core/java/com/android/server/MountService.java
public boolean onEvent(int code, String raw, String[] cooked) {
if (code == VoldResponseCode.VolumeStateChange) {
notifyVolumeStateChange(
cooked[2], cooked[3], Integer.parseInt(cooked[7]),
Integer.parseInt(cooked[10]));
}
}
private void notifyVolumeStateChange(String label, String path, int oldState, int newState) {
else if (newState == VolumeState.Mounted) {
if (DEBUG_EVENTS) Slog.i(TAG, "updating volume state mounted");
updatePublicVolumeState(volume, Environment.MEDIA_MOUNTED); //广播通知应用挂载完毕
action = Intent.ACTION_MEDIA_MOUNTED;
}
if (action != null) {
sendStorageIntent(action, volume, UserHandle.ALL);
}
}
三、项目问题