dumpsys是Android系统中的一个可执行文件,主要作用是将当前Android系统的一些信息dump出来,例如Activity、package等。是一个分析Android设备问题、查看运行状态、使用情况等十分有效的工具。可以获取各种系统信息和状态,如进程的PSS值,分析了解进程对RAM的占用情况。
dumpsys的语法提供了灵活的方式来获取和分析Android系统中各种服务的信息。基本语法结构如下:
adb shell dumpsys [-t timeout] [--help | -l | --skipservices | service[arguments] | -c | -h]
- [-t timeout]:可选参数,用于指定命令执行的超时时间(以秒为单位)。默认为10秒。
- [--help | -l | --skipservices | service[arguments] | -c | -h]:命令行选项,用于定制dumpsys的输出和行为。
--help:打印dumpsys的使用方法说明。
-l:列出dumpsys支持的所有系统服务列表。
--skipservices:指定不需要打印的服务列表。
service[arguments]:指定要查询的特定服务及其可选参数。通过指定服务名称,可以获取特定服务的详细信息。
-c:以机器友好的格式(通常是键值对)输出信息,对于自动化脚本解析可能很有用,对于人类阅读可能不太友好。
-h:用在指定的服务后面,打印服务支持哪些参数或如何使用该服务。
% adb shell dumpsys -l
Currently running services:
DisplayFeatureControl
DockObserver
MiuiBackup
MiuiCarService
MiuiInit
MiuiWifiService
ProcessManager
SchedBoostService
SlaveWifiService
SurfaceFlinger
accessibility
account
activity
activity_task
adb
如果dumpsys不加任何参数,会输出所有系统服务的详细信息,输出的内容是非常多的。实际解决具体问题时,我们通常只关注一些特定系统服务的输出,只需要将服务名作为dumpsys命令的参数,就可以只输出特定服务的信息。比如要输出磁盘使用的统计信息,则可以将diskstats这个系统服务名作为参数。
% adb shell dumpsys diskstats
Latency: 1ms [512B Data Write]
Recent Disk Write Speed (kB/s) = 45546
Data-Free: 53243072K / 113006560K total = 47% free
Cache-Free: 53243072K / 113006560K total = 47% free
System-Free: 0K / 5192648K total = 0% free
File-based Encryption: true
App Size: 16656406016
App Data Size: 33915740160
App Cache Size: 2662189568
Photos Size: 77041664
Videos Size: 17559552
Audio Size: 38887424
Downloads Size: 0
System Size: 128000000000
Other Size: 9238536192
工作原理
dumpsys基于Android系统的服务管理和进程间通信机制。通过调用Android系统底层的ServiceManager服务,来获取系统中所有已注册服务的信息。ServiceManager是Android系统中的一个核心服务,负责管理系统中的所有服务,提供统一的注册、发现和通信机制。
当dumpsys被调用时,会通过Binder进程间通信(IPC)框架与ServiceManager进行交互。Binder是Android提供的一套进程间相互通信的框架,允许不同的进程之间进行高效的通信和数据交换。通过Binder,dumpsys能够请求ServiceManager提供当前系统中所有已注册服务的列表,以及每个服务的详细信息。
ServiceManager会响应dumpsys的请求,返回系统中所有服务的状态信息。包括服务的名称、状态、运行时的统计数据等。dumpsys接收到这些信息后,会进行解析和整理,并以一种可读的方式展示。
int main(int argc, char* const argv[])
{
...
// 1. 首先获取 servicemanager
sp<IServiceManager> sm = defaultServiceManager();
...
// 2. 进行命令行参数解析
bool showListOnly = false;
if ((argc == 2) && (strcmp(argv[1], "-l") == 0)) {
// 2.1 当参数仅为 "-l" 时,设置只罗列出所有的服务名
showListOnly = true;
}
if ((argc == 1) || showListOnly) {
// 2.2 当不带任何参数时,则附加 "-a" 参数,表示输出所有系统服务信息
services = sm->listServices();
services.sort(sort_func);
args.add(String16("-a"));
} else {
// 2.3 当带了一个参数时,表示仅输出指定的系统服务信息
services.add(String16(argv[1]));
for (int i=2; i<argc; i++) {
args.add(String16(argv[i]));
}
}
// 3. 罗列出services这个数组中的服务名称,到这一步为止,都还只是在dumpsys本身的逻辑中转悠
const size_t N = services.size();
if (N > 1) {
aout << "Currently running services:" << endl;
for (size_t i=0; i<N; i++) {
sp<IBinder> service = sm->checkService(services[i]);
if (service != NULL) {
aout << " " << services[i] << endl;
}
}
}
if (showListOnly) {
return 0;
}
// 4. 输出services这个数组中所包含系统服务的详细信息
for (size_t i=0; i<N; i++) {
sp<IBinder> service = sm->checkService(services[i]);
if (service != NULL) {
...
// 4.1 调用service的dump方法,来输出service的具体信息
int err = service->dump(STDOUT_FILENO, args);
...
}
...
}
return 0;
}
- 获取servicemanager,所有的系统服务都会向servicemanager注册
- 进行命令行参数解析,根据参数的不同设置后续的执行指令序列
- 简单的罗列了一下需要输出的系统服务名称
- 调用具体系统服务的dump()方法完成系统服务详细信息的输出
以上面adb shell dumpsys diskstats命令为例,最终调用dump()方法完成输出:
protected void dump(FileDescriptor fd, PrintWriter pw, String[] args) {
// 1. 权限检查
mContext.enforceCallingOrSelfPermission(android.Manifest.permission.DUMP, TAG);
// 2. 生成一个大小为512B的临时文件
byte[] junk = new byte[512];
for (int i = 0; i < junk.length; i++) junk[i] = (byte) i; // Write nonzero bytes
File tmp = new File(Environment.getDataDirectory(), "system/perftest.tmp");
// 3. 将512B的临时文件写入磁盘,目的是为了快速的测试写磁盘的延迟
long before = SystemClock.uptimeMillis();
...
fos = new FileOutputStream(tmp);
fos.write(junk);
...
long after = SystemClock.uptimeMillis();
...
pw.print("Latency: ");
pw.print(after - before);
pw.println("ms [512B Data Write]");
...
// 4. 输出Data, Cache和System这几个分区的磁盘使用信息
reportFreeSpace(Environment.getDataDirectory(), "Data", pw);
reportFreeSpace(Environment.getDownloadCacheDirectory(), "Cache", pw);
reportFreeSpace(new File("/system"), "System", pw);
....
}