Android vold通讯篇(CommandListener)
来源:互联网 发布:直接引用vue.js没反应 编辑:程序博客网 时间:2024/06/08 19:22
前一篇文章: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的通讯核心。
- Android vold通讯篇(CommandListener)
- vold CommandListener
- Android vold进程二 VolumeManager和CommandListener简介
- android vold:图解VOLD
- Android vold核心篇(VolumeManager)
- Android VOLD
- Android vold
- android vold
- Android Vold
- ANDROID中的VOLD分析
- Android vold浅析
- Android VOLD 分析
- Vold 2.0 ---- Android-2.3
- android 2.2 vold
- Android 2.1 Vold 分析
- Android Vold架构
- ANDROID中的VOLD分析
- Android Vold 分析
- 仿美团实现城市定位。
- 如何在Visual Studio项目中正确添加汇编代码
- 网络设备入门测试
- 前端学习体系
- HDOJ1166(线段树,树状数组)
- Android vold通讯篇(CommandListener)
- IT行业中的“大灰狼”与“小羔羊”
- hdu3664(递推)
- OpenWrt C/C++ Development with Eclipse(Eclipse下的Openwrt开发)
- splay复习小记
- 有一副由NxN矩阵表示的图像,这里每个像素用一个int表示,请编写一个算法,在不占用额外内存空间的情况下(即不使用缓存矩阵),将图像顺时针旋转90度。 给定一个NxN的矩阵,和矩阵的阶数N,请返回旋转
- PHP版本高于5.5时,curl文件上传必须使用CurlFile对象
- C++常用的函参类型解析
- 《广播电视安全播出事件/事故管理规定》