前一篇文章:Androidvold核心篇,介绍了vold接收到NetlinkManager发来的内核消息进行对应的处理后(包含挂载卸载等),将处理后的结果发送到FrameWrok,具体是怎么发送的,以及怎么接收从Framework发来的消息,在本文解析。
一、CommandListener类的实现
我们回到Main.cpp的主函数main中,里面有定义一个变量如下:
CommandListener *cl;
cl = new CommandListener();
那CommandListener具体是做什么用的呢?看以下代码:
class CommandListener : public FrameworkListener {
public:
CommandListener();
virtual ~CommandListener() {}
private:
static void dumpArgs(int argc, char **argv, int argObscure);
class DumpCmd : public VoldCommand {
public:
DumpCmd();
virtual ~DumpCmd() {}
int runCommand(SocketClient *c, int argc, char ** argv);
};
class VolumeCmd : public VoldCommand {
public:
VolumeCmd();
virtual ~VolumeCmd() {}
int runCommand(SocketClient *c, int argc, char ** argv);
};
class AsecCmd : public VoldCommand {
public:
AsecCmd();
virtual ~AsecCmd() {}
int runCommand(SocketClient *c, int argc, char ** argv);
private:
void listAsecsInDirectory(SocketClient *c, const char *directory);
};
class ObbCmd : public VoldCommand {
public:
ObbCmd();
virtual ~ObbCmd() {}
int runCommand(SocketClient *c, int argc, char ** argv);
};
class StorageCmd : public VoldCommand {
public:
StorageCmd();
virtual ~StorageCmd() {}
int runCommand(SocketClient *c, int argc, char ** argv);
};
class XwarpCmd : public VoldCommand {
public:
XwarpCmd();
virtual ~XwarpCmd() {}
int runCommand(SocketClient *c, int argc, char ** argv);
};
class CryptfsCmd : public VoldCommand {
public:
CryptfsCmd();
virtual ~CryptfsCmd() {}
int runCommand(SocketClient *c, int argc, char ** argv);
};
class FstrimCmd : public VoldCommand {
public:
FstrimCmd();
virtual ~FstrimCmd() {}
int runCommand(SocketClient *c, int argc, char ** argv);
};
};
我们知道它继承自
FrameworkListener,且定义了很多了内部类,这些内部类都继承自
VoldCommand,关于
VoldCommand稍后我们会介绍。
那么FrameworkListener类又是干什么的呢?
class FrameworkListener : public SocketListener {
public:
static const int CMD_ARGS_MAX = 26;
/* 1 out of errorRate will be dropped */
int errorRate;
private:
int mCommandCount;
bool mWithSeq;
FrameworkCommandCollection *mCommands;
public:
FrameworkListener(const char *socketName);
FrameworkListener(const char *socketName, bool withSeq);
virtual ~FrameworkListener() {}
protected:
void registerCmd(FrameworkCommand *cmd);
virtual bool onDataAvailable(SocketClient *c);
private:
void dispatchCommand(SocketClient *c, char *data);
void init(const char *socketName, bool withSeq);
};
原来
FrameworkListener继承自
SocketListener;
现在请关注一下FrameworkListener的两个构造函数,我们发现它的构造函数都需要有参数,但是CommandListener的构造函数确没有,
那就看一下CommandListener的构造函数的实现,如下:
CommandListener::CommandListener() :
FrameworkListener("vold", true) {
registerCmd(new DumpCmd());
registerCmd(new VolumeCmd());
registerCmd(new AsecCmd());
registerCmd(new ObbCmd());
registerCmd(new StorageCmd());
registerCmd(new XwarpCmd());
registerCmd(new CryptfsCmd());
registerCmd(new FstrimCmd());
}
哦,原来是给
FrameworkListener传了一个常量的字符串“vold”,通过代码的追踪发现,
这个参数传到了SocketListener中,根据该字符串创建了一个套接字,
将该套接字包装到了SocketClient类对象,而该对象保存在mClients集合变量中。
从这个构造函数中,还可以发现,这里注册了很多的类对象,而这些类都是在CommandListener中创建的内部类(参考CommandListener的实现)。
那么registerCmd是干什么用的呢,此时需要跳转到FrameworkListener的registerCmd函数:
void FrameworkListener::registerCmd(FrameworkCommand *cmd) {
mCommands->push_back(cmd);
}
关于mCommands成员变量,:
FrameworkCommandCollection *mCommands;
而FrameworkCommandCollection 实际是一个FrameworkCommand类对象的集合。
通过registerCmd可以推断出在CommandListener中创建的内部类应该都为FrameworkCommand的子类,从CommandListener的内部类的定义可以知道,所有的内部内都继承自VoldCommand,而VoldCommand类则是简单的继承钰FrameworkCommand,代码如下(前面有提到过该类,但是没有详细介绍):
class VoldCommand : public FrameworkCommand {
public:
VoldCommand(const char *cmd);
virtual ~VoldCommand() {}
};
到这里,可以说把跟CommandListener类相关的类都理清了。
总结一下:
CommandListener的最终根父类为SocketListener;
CommandListener对象在构造的过程中,在SocketListener构造函数中创建了“vold”套接字;
CommandListener对象在构造的过程中,注册了一些从FrameworkCommand类派生的类对象;
二、CommandListener是如何发挥作用的
在main函数中,有这么一段代码:
if (cl->startListener()) {
SLOGE("Unable to start CommandListener (%s)", strerror(errno));
exit(1);
}
由第一段“CommandListener的实现”知道,CommandListener最终的根父类是SocketListener,在上面代码中调用的startListener函数正是在SocketListener中实现的,其实关于SocketListener的startListener函数在我的前一遍博文
Androidvold启动篇中分析过,此处简单提一下:
startListener函数基于前面创建的vold套接字,对Framework发送的消息进行监听,并且传递到FrameworkListener::onDataAvailable的函数中进行处理,再到FrameworkListener::dispatchCommand函数中进行处理,在该函数中的核心代码如下:
for (i = mCommands->begin(); i != mCommands->end(); ++i) {
FrameworkCommand *c = *i;
if (!strcmp(argv[0], c->getCommand())) {
if (c->runCommand(cli, argc, argv)) {
SLOGW("Handler '%s' error (%s)", c->getCommand(), strerror(errno));
}
goto out;
}
}
也就是说,此时从Framework发下来的消息传递到了从VoldCommand类派生的子类中,
下面分析一个派生类: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], "debug")) {
if (argc != 3 || (argc == 3 && (strcmp(argv[2], "off") && strcmp(argv[2], "on")))) {
cli->sendMsg(ResponseCode::CommandSyntaxError, "Usage: volume debug <off/on>", false);
return 0;
}
vm->setDebug(!strcmp(argv[2], "on") ? true : false);
} 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")) &&
(argc == 4 && strcmp(argv[3], "force_and_revert")))) {
cli->sendMsg(ResponseCode::CommandSyntaxError, "Usage: volume unmount <path> [force|force_and_revert]", false);
return 0;
}
bool force = false;
bool revert = false;
if (argc >= 4 && !strcmp(argv[3], "force")) {
force = true;
} else if (argc >= 4 && !strcmp(argv[3], "force_and_revert")) {
force = true;
revert = true;
}
rc = vm->unmountVolume(argv[2], force, revert);
} else if (!strcmp(argv[1], "format")) {
if (argc < 3 || argc > 4 ||
(argc == 4 && strcmp(argv[3], "wipe"))) {
cli->sendMsg(ResponseCode::CommandSyntaxError, "Usage: volume format <path> [wipe]", false);
return 0;
}
bool wipe = false;
if (argc >= 4 && !strcmp(argv[3], "wipe")) {
wipe = true;
}
rc = vm->formatVolume(argv[2], wipe);
} else if (!strcmp(argv[1], "share")) {
if (argc != 4) {
cli->sendMsg(ResponseCode::CommandSyntaxError,
"Usage: volume share <path> <method>", false);
return 0;
}
rc = vm->shareVolume(argv[2], argv[3]);
} else if (!strcmp(argv[1], "unshare")) {
if (argc != 4) {
cli->sendMsg(ResponseCode::CommandSyntaxError,
"Usage: volume unshare <path> <method>", false);
return 0;
}
rc = vm->unshareVolume(argv[2], argv[3]);
} else if (!strcmp(argv[1], "shared")) {
bool enabled = false;
if (argc != 4) {
cli->sendMsg(ResponseCode::CommandSyntaxError,
"Usage: volume shared <path> <method>", false);
return 0;
}
if (vm->shareEnabled(argv[2], argv[3], &enabled)) {
cli->sendMsg(
ResponseCode::OperationFailed, "Failed to determine share enable state", true);
} else {
cli->sendMsg(ResponseCode::ShareEnabledResult,
(enabled ? "Share enabled" : "Share disabled"), false);
}
return 0;
} else if (!strcmp(argv[1], "mkdirs")) {
if (argc != 3) {
cli->sendMsg(ResponseCode::CommandSyntaxError, "Usage: volume mkdirs <path>", false);
return 0;
}
rc = vm->mkdirs(argv[2]);
} 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;
}
通过上面的代码可知,此函数实现了挂载、共享、格式化等操作,并且操作完成或者发生错误时,会将消息返回给Framewrok。
三、vold向上层发送消息
在Android vold核心篇的最后,我们提到了疑问,vold向Framewrok层发送消息时使用的SocketListener的成员变量mClients(SocketClientCollection类型)是如何来的,以及mClient集合的元素的套接字又是怎么来的,通过以上分析我相信大家应该知道了吧。
四、总结
CommandListener的作用:
将vold层的消息发送到Framewrok层
接收Framewrok的消息,进行处理
CommandListener就是vold与Framework的通讯核心。