adb shell dumpsys 工作原理分析

作为一个Android开发者,对adb的使用都不会陌生。

Android 调试桥 (adb) 是一种功能多样的命令行工具,可让您与设备进行通信。adb 命令可用于执行各种设备操作(例如安装和调试应用),并提供对 Unix shell(可用来在设备上运行各种命令)的访问权限。这里就不做更多介绍了。更多adb 命令使用请访问 https://developer.android.com/studio/command-line/adb 进一步了解。

今天想说的是adb shell命令的使用 ,shell 模式下有很多可以使用的命令,可以通过adb shell ls /system/bin/ 查看,也可以先adb shell进入交互模式,然后再进入/system/bin/ 查看

我们可以发现很多命令和我们平常使用的Linux命令很相识。比如chomd ,cat 等等。其实一些常用的命令就可以解决我们平时遇到的绝大多数的问题。

adb shell  dumpsys

adb shell settings

adb shell  am/pm

adb shell setprop/getprop

我们先以dumpsys命令为例,其他命令过程类似。

dumpsys介绍

dumpsys 是一种在 Android 设备上运行的工具,可提供有关系统服务的信息。获取在连接的设备上运行的所有系统服务的诊断输出。此输出通常比想要的更详细,因此需要使用命令行选项进行过滤,仅获取感兴趣的系统服务的输出。

语法

使用 dumpsys 的一般语法如下:

获取所连接设备的所有系统服务的诊断输出,只需运行 adb shell dumpsys。

 例如:

  • dumpsys activity //查询AMS服务相关信息
  • dumpsys window //获取所有window相关的信息
  • dumpsys cpuinfo //查询CPU情况
  • dumpsys meminfo //查询内存情况

可查询的服务有很多,可通过下面任一命令查看当前系统所支持的dump服务:

  • adb shell dumpsys -l
  • adb shell service list

 

果要使输出更加可控,还需要在命令中添加相应服务来进行指定。

命令行选项

下表列出了使用 dumpsys 时的可用选项。

选项

说明

-t timeout

指定超时期限(秒)。如果未指定,默认值为 10 秒。

--help

输出 dumpsys 工具的帮助文本。

-l

输出可与 dumpsys 配合使用的系统服务的完整列表。

--skip services

指定您不希望包含在输出中的 services。

service [arguments]

指定您希望输出的 service。某些服务可能允许您传递可选 arguments。您可以通过将 -h 选项与服务名称一起传递来了解这些可选参数,如下所示:

-c

指定某些服务时,附加此选项能以计算机可读的格式输出数据。

dumpsys方法在分析服务状态和信息十分有用。那我们执行命令后,系统是怎么响应我们把信息dump出来的呢?

 

dumpsys 实现原理

既然dumpsys 是一个可执行文件,必然是先找到其mk文件:/frameworks/native/cmds/dumpsys/Android.mk

1.int main(int argc, char* const argv[]){

2.    ...

3.    sp<IServiceManager> sm = defaultServiceManager();

4.    ...

5.    Vector<String16> services;

6.    ...

7.    services = sm->listServices();

8.    ...

9.    const size_t N = services.size();

10.    

11.    for (size_t i = 0; i < N; i++) {

12.        const String16& serviceName = services[i];

13.       sp<IBinder> service = sm_->checkService(serviceName);

14.    if (service == nullptr) {

15.        std::cerr << "Can't find service: " << serviceName << std::endl;

16.        return NAME_NOT_FOUND;

17.    }

18.     err = service->dump(remote_end.get(), args); //这里调用的是java层服务对应的dump方法

19.        }

20.    });          

21.    }

22.

23.    return 0;}

先通过defaultServiceManager()函数获得ServiceManager对象,然后根据dumpsys传进来的参数通过函数checkService来找到具体的service, 并执行该service的dump方法,然后执行该service的dump函数,达到dump service的目的。

以我们最熟悉的adb shell dumpsys activity 为例,这条命令将输入大量信息

这些信息在源码中的位置在哪里呢?

我们知道系统服务的调用经常通过ServiceManager.getService(xx)的形式获取,

系统核心服务在SystemServer  被启动和注册(注册通过ServiceManager.addService)

adb shell dumpsys activity 查找的就是被注册为activity的服务即ActivityManagerService即为要找到的服务。

 SystemServer.java 
   
      // Set up the Application instance for the system process and get started.
        t.traceBegin("SetSystemProcess");
        mActivityManagerService.setSystemProcess();
        t.traceEnd();


ActivityManagerService.java

       public static final String ACTIVITY_SERVICE = "activity";


       public void setSystemProcess() {
        try {
            ServiceManager.addService(Context.ACTIVITY_SERVICE, this, /* allowIsolated= */ true,
                    DUMP_FLAG_PRIORITY_CRITICAL | DUMP_FLAG_PRIORITY_NORMAL | DUMP_FLAG_PROTO);
            ServiceManager.addService(ProcessStats.SERVICE_NAME, mProcessStats);
            ServiceManager.addService("meminfo", new MemBinder(this), /* 

..........................


        }
}

在代码中通过 快捷键 ctrl + f12搜索dump()方法,

  @Override
    protected void dump(FileDescriptor fd, PrintWriter pw, String[] args) {
        PriorityDump.dump(mPriorityDumper, fd, pw, args);
    }

核心信息打印的实现都在 mPriorityDumper  这个实例对象中。

    /**
     * Helper class which strips out priority and proto arguments then calls the dump function with
     * the appropriate arguments. If priority arguments are omitted, function calls the legacy
     * dump command.
     * If priority arguments are omitted all sections are dumped, otherwise sections are dumped
     * according to their priority.
     */
    private final PriorityDump.PriorityDumper mPriorityDumper = new PriorityDump.PriorityDumper() {
        @Override
        public void dumpCritical(FileDescriptor fd, PrintWriter pw, String[] args,
                boolean asProto) {
            if (asProto) return;
            doDump(fd, pw, new String[]{"activities"}, asProto);
            doDump(fd, pw, new String[]{"service", "all-platform-critical"}, asProto);
        }

        @Override
        public void dumpNormal(FileDescriptor fd, PrintWriter pw, String[] args, boolean asProto) {
            doDump(fd, pw, new String[]{"-a", "--normal-priority"}, asProto);
        }

        @Override
        public void dump(FileDescriptor fd, PrintWriter pw, String[] args, boolean asProto) {
            doDump(fd, pw, args, asProto);
        }
    };

小结

通过熟悉dumpsys的流程,可以帮助我们更深入的理解和使用这些命令工具,提高开发效率。通过对dumpsys执行流程的分析,我们知道某些参数是如何打印出来的,不清楚什么意思也可以在对应的xxManagerService中找到对应的dump方法。然后后结合源码加深理解或者进行二次开发。

  • 0
    点赞
  • 3
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值