Android dumpsys介绍
文章目录
- 一、需求
- 二、环境
- 三、相关概念
- 3.1 dumpsys
- 3.2 Binder
- 3.3 管道
- 四、dumpsys指令的使用
- 4.1 dumpsys使用
- 4.2 dumpsys指令语法
- 五、详细设计
- 5.1 dumpsys流程图
- 5.2 dumpsys查看电池信息
- 5.2.1 dumpsys battery指令
- 5.2.2 service->dump打印函数
- 5.3 dumpsys源码分析
- 5.3.1 dumpsys服务编译
- 5.3.2 dumpsys入口函数
- 5.3.3 dumpsys服务打印
- 5.3.3.1 dumpsys解析参数
- 5.3.3.2 skippedServices列表构造
- 5.3.3.3 获取支持服务列表
- 5.3.3.4 打印支持服务列表
- 5.3.3.5 打印目标服务
- 六、dumpsys的应用
- 6.1 dumpsys常用指令
- 七、参考资料
一、需求
- 了解dumpsys原理,助于我们进一步了解Android系统的设计
- 帮助我们分析问题,定位系统状态
- 设计新功能的需要
二、环境
- 版本:Android 12
- 平台:SL8541E SPRD
三、相关概念
3.1 dumpsys
dumpsys 是一种在 Android 设备上运行的工具,可提供有关系统服务的信息。可以使用 Android 调试桥 (adb) 从命令行调用 dumpsys,获取在连接的设备上运行的所有系统服务的诊断输出。
3.2 Binder
Binder是Android提供的一套进程间相互通信框架。用来实现多进程间发送消息,同步和共享内存。
3.3 管道
管道是一种IPC通信方式,分为有名管道和无名管道,无论是有名管道还是无名管道其原理都是在内核开辟一块缓存空间,这段缓存空间的操作是通过文件读写方式进行的。
有名管道与无名管道:
有名管道: 有名管道的通信可以通过管道名进行通信,进程间不需要有关系。
无名管道: 无名管道就是匿名管道,匿名管道通信的进程必须是父子进程。
管道为分半双工和全双工:
半双工: 半双工管道是单向通信,进程1只能向管道写数据,进程2只能从管道读取数据。只有一个代表读或者写的FD(文件描述符)。
全双工: 全双工管道是双向通信,有两个文件描述符,代表读和写。
四、dumpsys指令的使用
4.1 dumpsys使用
如下为执行"adb shell dumpsys"指令,控制台打印的内容,其使用如下:
dumpsys执行
4.2 dumpsys指令语法
(1)使用 dumpsys 的一般语法如下:
adb shell dumpsys [-t timeout] [--help | -l | --skip services | service [arguments] | -c | -h]
(2)如需获取所连接设备的所有系统服务的诊断输出,请运行 adb shell dumpsys。不过,这样输出的信息比您通常想要的信息多得多。若要使输出更加可控,您可以通过在命令中添加相应服务来指定要检查的服务。例如,下面的命令会提供输入组件(如触摸屏或内置键盘)的系统数据:
adb shell dumpsys input
(3)如需查看可与 dumpsys 配合使用的系统服务的完整列表,请使用以下命令:
adb shell dumpsys -l
(4)命令行选项如下:
选项 说明 -t timeout 指定超时期限(秒)。如果未指定,默认值为 10 秒。 –help 输出 dumpsys 工具的帮助文本。 -l 输出可与 dumpsys 配合使用的系统服务的完整列表。 –skip services 指定您不希望包含在输出中的 services。 service [arguments] 指定您希望输出的 service。某些服务可能允许您传递可选 arguments。如需了解这些可选参数,请将 -h 选项与服务一起传递:
adb shell dumpsys procstats -h-c 指定某些服务时,附加此选项能以计算机可读的格式输出数据。 -h 对于某些服务,附加此选项可查看该服务的帮助文本和其他选项。 五、详细设计
5.1 dumpsys流程图
5.2 dumpsys查看电池信息
5.2.1 dumpsys battery指令
5.2.2 service->dump打印函数
@frameworks\base\services\core\java\com\android\server\BatteryService.java private final class BinderService extends Binder { @Override protected void dump(FileDescriptor fd, PrintWriter pw, String[] args) { if (!DumpUtils.checkDumpPermission(mContext, TAG, pw)) return; if (args.length > 0 && "--proto".equals(args[0])) { dumpProto(fd); } else { dumpInternal(fd, pw, args); } } ... } private void dumpInternal(FileDescriptor fd, PrintWriter pw, String[] args) { synchronized (mLock) { if (args == null || args.length == 0 || "-a".equals(args[0])) { pw.println("Current Battery Service state:"); if (mUpdatesStopped) { pw.println(" (UPDATES STOPPED -- use 'reset' to restart)"); } pw.println(" AC powered: " + mHealthInfo.chargerAcOnline); pw.println(" USB powered: " + mHealthInfo.chargerUsbOnline); pw.println(" Wireless powered: " + mHealthInfo.chargerWirelessOnline); pw.println(" Max charging current: " + mHealthInfo.maxChargingCurrent); pw.println(" Max charging voltage: " + mHealthInfo.maxChargingVoltage); pw.println(" Charge counter: " + mHealthInfo.batteryChargeCounter); pw.println(" status: " + mHealthInfo.batteryStatus); pw.println(" health: " + mHealthInfo.batteryHealth); pw.println(" present: " + mHealthInfo.batteryPresent); pw.println(" level: " + mHealthInfo.batteryLevel); pw.println(" scale: " + BATTERY_SCALE); pw.println(" voltage: " + mHealthInfo.batteryVoltage); pw.println(" temperature: " + mHealthInfo.batteryTemperature); pw.println(" technology: " + mHealthInfo.batteryTechnology); } else { Shell shell = new Shell(); shell.exec(mBinderService, null, fd, null, args, null, new ResultReceiver(null)); } } }
5.3 dumpsys源码分析
5.3.1 dumpsys服务编译
dumpsys是个二进制可执行程序,其通过bp进行编译,并最终打包到system分区(system/bin/dumpsys)。
@frameworks\native\cmds\dumpsys\android.bp cc_binary { name: "dumpsys", defaults: ["dumpsys_defaults"], srcs: [ "main.cpp", ], }
5.3.2 dumpsys入口函数
我们通过执行adb指令 “adb shell dumpsys”,可以启动dumpsys服务,其对应的入口函数如下:
@frameworks\native\cmds\dumpsys\main.cpp int main(int argc, char* const argv[]) { signal(SIGPIPE, SIG_IGN); sp sm = defaultServiceManager();//获取SM对象 fflush(stdout); if (sm == nullptr) { ALOGE("Unable to get default service manager!"); std::cerr ... while (1) { ... c = getopt_long(argc, argv, "+t:T:l", longOptions, &optionIndex);//获取指令参数 ... switch (c) { case 0://长参数 if (!strcmp(longOptions[optionIndex].name, "skip")) {//跳过某些服务打印 skipServices = true; } else if (!strcmp(longOptions[optionIndex].name, "proto")) { asProto = true; } else if (!strcmp(longOptions[optionIndex].name, "help")) {//指令帮助 usage(); return 0; } else if (!strcmp(longOptions[optionIndex].name, "priority")) { ... } else if (!strcmp(longOptions[optionIndex].name, "pid")) {//只显示服务的pid type = Type::PID; } else if (!strcmp(longOptions[optionIndex].name, "thread")) {//仅显示进程使用情况 type = Type::THREAD; } break; case 't'://超时时间设置,默认10秒 ... break; case 'T'://超时时间设置,默认10秒 ... break; case 'l'://显示支持的服务列表 showListOnly = true; break; default://其他参数 fprintf(stderr, "\n"); usage(); return -1; } } ... }
h55.3.3.2 skippedServices列表构造/h5 p dumpsys内部构造了skippedServices集合,用于记录需要忽略的服务。/p pre class="brush:python;toolbar:false"@frameworks\native\cmds\dumpsys\dumpsys.cpp int Dumpsys::main(int argc, char* const argv[]) { ... for (int i = optind; i 1 || showListOnly) { // first print a list of the current services std::cout sp//创建管道,用于读取service端数据 ... } ... redirectFd_ = unique_fd(sfd[0]); unique_fd remote_end(sfd[1]); sfd[0] = sfd[1] = -1; // dump blocks until completion, so spawn a thread.. activeThread_ = std::thread([=, remote_end{std::move(remote_end)}]() mutable {//创建线程 status_t err = 0; switch (type) { case Type::DUMP: err = service-dump(remote_end.get(), args);//调用dump函数 break; ... } ... }); return OK; }