2

探秘Android系统:dumpsys命令获取系统服务详细信息

 4 weeks ago
source link: https://www.51cto.com/article/785899.html
Go to the source link to view the article. You can view the picture content, updated content and better typesetting reading experience. If the link is broken, please click the button below to view the snapshot at that time.

探秘Android系统:dumpsys命令获取系统服务详细信息

作者:Reathin 2024-04-11 08:26:34
dumpsys是Android系统中的一个可执行文件,主要作用是将当前Android系统的一些信息dump出来,例如Activity、package等。

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;
}
  1. 获取servicemanager,所有的系统服务都会向servicemanager注册
  2. 进行命令行参数解析,根据参数的不同设置后续的执行指令序列
  3. 简单的罗列了一下需要输出的系统服务名称
  4. 调用具体系统服务的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);
    ....
}

About Joyk


Aggregate valuable and interesting links.
Joyk means Joy of geeK