dumpsys的使用笔记

dumpsys的使用笔记

概述

   Android系统中有很多服务,不同版本的Android系统,服务不尽相同,并且不同ROM厂商也提供了其定制的服务,为了方便查看这些服务的信息与状态,Android提供了dumpsys工具。

   手机连接电脑后可以执行adb shell dumpsys -l,即可查看当前所有的系统服务名称。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
$ adb shell dumpsys -l
AAL
DmAgent
DockObserver
GbaService
GpuAppSpectatorService
GuiExtService
IIccPhoneBookMz
NvRAMAgent
PQ
SurfaceFlinger
access_control
accessibility
account
activity
alarm
alphame_server
android.hardware.fingerprint.IFingerprintDaemon
android.hardware.fingerprint.IGoodixFingerprintDaemon
android.hardware.ifaa.IIfaaDaemon
android.security.keystore
android.service.gatekeeper.IGateKeeperService
...

   接着就可以通过dumpsys + name查看某个服务的具体信息。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
$ adb shell dumpsys battery
Current Battery Service state:
AC powered: false
USB powered: true
Wireless powered: false
Max charging current: 0
Max charging voltage: 0
Charge counter: 0
status: 2
health: 2
present: true
level: 89
scale: 100
voltage: 4253
temperature: 280
technology: Li-ion

常用的指令

   列举一些常用的dump指令

1. 获取包信息

1
2
adb shell dumpsys package packgename
用以获取某个应用包的信息,不加包名则会列出所有包信息

2. 获取窗口信息

1
2
adb shell dumpsys window
用以获取窗口信息

3. 四大组件相关信息

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
adb shell dumpsys activity
获取所有四大组件相关的信息
adb shell dumpsys activity a packagename
获取某个应用的Activity信息
adb shell dumpsys activity s packagename
获取某个应用的Service信息
adb shell dumpsys activity b packagename
获取某个应用的Broadcast信息
adb shell dumpsys activity prov packagename
获取某个应用的Provider信息
adb shell dumpsys activity p packagename
查询某个应用的进程状态
adb shell dumpsys activity top | grep ACTIVITY
要获取当前界面的Activity
adb shell dumpsys activity top
获取当前界面的UI信息
adb shell dumpsys notification
获取通知信息

4. 手机信息相关信息

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
adb shell dumpsys alarm
获取手机闹钟信息
adb shell dumpsys battery
获取设备电池信息
adb shell dumpsys power
获取电源管理信息
adb shell dumpsys wifi
获取wifi相关信息
adb shell dumpsys netstats
获取网络状态信息
adb shell dumpsys display
获取显示信息
adb shell dumpsys display | grep DisplayDeviceInfo
获取屏幕信息
adb shell dumpsys cpuinfo
获取CPU信息
adb shell dumpsys meminfo
获取内存信息
adb shell dumpsys diskstats
获取磁盘信息
adb shell dumpsys meminfo packagename
获取某个应用的内存使用信息

注:大部分母指令后加-h可以获取帮助信息,如adb shell dumpsys package -h

实现原理

   简单的介绍下实现原理

   找到其对应Android的配置文件,位于frameworks/native/cmds/dumpsys目录下,其配置如下。

1
2
3
4
5
6
7
8
9
10
11
LOCAL_PATH:= $(call my-dir)
include $(CLEAR_VARS)
LOCAL_SRC_FILES:= \
dumpsys.cpp
...
LOCAL_MODULE:= dumpsys
include $(BUILD_EXECUTABLE)

   可以看到配置文件很简单,最重要的是dumpsys.cpp文件,定位到位置frameworks/native/cmds/dumpsys/dumpsys.cpp,查看其main方法。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
int main(int argc, char* const argv[])
{
signal(SIGPIPE, SIG_IGN);
//获取SystemServiceManager对象
sp<IServiceManager> sm = defaultServiceManager();
...
//保存服务的集合
Vector<String16> services;
//接收参数
Vector<String16> args;
Vector<String16> skippedServices;
...
while (1) {
int c;
int optionIndex = 0;
//根据输入参数获取对应的值
c = getopt_long(argc, argv, "+t:l", longOptions, &optionIndex);
if (c == -1) {
break;
}
//根据对应的值选择输出对应的dump信息序列
switch (c) {
case 0:
//跳过服务以及帮助信息
if (!strcmp(longOptions[optionIndex].name, "skip")) {
skipServices = true;
} else if (!strcmp(longOptions[optionIndex].name, "help")) {
usage();
return 0;
}
break;
case 't':
//超时设置
{
char *endptr;
timeoutArg = strtol(optarg, &endptr, 10);
if (*endptr != '\0' || timeoutArg <= 0) {
fprintf(stderr, "Error: invalid timeout number: '%s'\n", optarg);
return -1;
}
}
break;
case 'l':
//当值为'l',只列出所有服务名
showListOnly = true;
break;
default:
fprintf(stderr, "\n");
usage();
return -1;
}
}
...
if (services.empty() || showListOnly) {
// gets all services
//获取所有服务
services = sm->listServices();
//排序
services.sort(sort_func);
args.add(String16("-a"));
}
//计算服务个数
const size_t N = services.size();
...
for (size_t i = 0; i < N; i++) {
//获取服务名称
String16 service_name = std::move(services[i]);
if (IsSkipped(skippedServices, service_name)) continue;
//检查服务
sp<IBinder> service = sm->checkService(service_name);
if (service != NULL) {
...
// dump blocks until completion, so spawn a thread..
//通过线程打印dump信息
std::thread dump_thread([=, remote_end { std::move(remote_end) }]() mutable {
//打印dump信息
int err = service->dump(remote_end.get(), args);
...
}
});
//超时
auto timeout = std::chrono::seconds(timeoutArg);
...
}
}
return 0;

   从上述的代码里,可以看出,dump的大致逻辑为:

  1. 通过defaultServiceManager获取SystemServiceManager的对象(SystemServiceManager顾名思义就是用来管理所有的服务);
  2. 通过SystemServiceManager获取系统所有服务,并排序;
  3. 解析接收的参数,根据参数的不同设置后续的执行指令序列;
  4. 从SystemServiceManager中找到需要输出的服务对象,执行该服务的dump方法
  5. 完成所有dump信息打印。

版权声明:本文为博主原创文章,转载请注明出处KidSea

小额赞助,鼓励作者写出更好的文章