返回顶部
首页 > 资讯 > 移动开发 >Android dumpsys介绍
  • 365
分享到

Android dumpsys介绍

1024程序员节 2023-10-26 10:10:03 365人浏览 薄情痞子
摘要

文章目录 一、需求二、环境三、相关概念3.1 dumpsys3.2 Binder3.3 管道 四、dumpsys指令的使用4.1 dumpsys使用4.2 dumpsys指令语法 五、

文章目录

一、需求

  1. 了解dumpsys原理,助于我们进一步了解Android系统的设计
  2. 帮助我们分析问题,定位系统状态
  3. 设计新功能的需要

二、环境

  1. 版本:Android 12
  2. 平台: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.javaprivate 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.bpcc_binary {    name: "dumpsys",    defaults: ["dumpsys_defaults"],    srcs: [        "main.cpp",    ],}

5.3.2 dumpsys入口函数

        我们通过执行adb指令 “adb shell dumpsys”,可以启动dumpsys服务,其对应的入口函数如下:

@frameworks\native\cmds\dumpsys\main.cppint main(int argc, char* const argv[]) {    signal(SIGPIPE, SIG_IGN);    sp<IServiceManager> sm = defaultServiceManager();//获取SM对象    fflush(stdout);    if (sm == nullptr) {        ALOGE("Unable to get default service manager!");        std::cerr << "dumpsys: Unable to get default service manager!" << std::endl;        return 20;    }    Dumpsys dumpsys(sm.get());    return dumpsys.main(argc, argv);//进入dumpsys服务}

        这边比较关键的点是获取ServiceManager对象
        大家通过打印可以发现,dumpsys指令打印的数据是java进程的dump函数,而dumpsys也是独立的一个进程,那么dumpsys进程又是怎么和多个java进程通信的呢?没错,就是通过ServiceManager对象。
        那么,ServiceManager对象是什么呢?ServiceManager是Binder IPC通信的管家,本身也是一个Binder服务,他相当于 “DNS服务器”,内部存储了serviceName与其Binder Service的对应关系,管理Java层和native层的service,支持addService()、getService()、checkService、listServices()等功能。(Binder机制此处就不展开细说)

5.3.3 dumpsys服务打印

5.3.3.1 dumpsys解析参数

        当我们使用dumpsys指令,打印的数据太过冗长,一般会配合相关参数进行使用,例如:“dumpsys -l”、“dumpsys -t 100 battery”、“dumpsys --help”,第一步我们会先解析目标参数。

@frameworks\native\cmds\dumpsys\dumpsys.cppint Dumpsys::main(int argc, char* const argv[]) {    ...    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;        }    }    ...}
5.3.3.2 skippedServices列表构造

        dumpsys内部构造了skippedServices集合,用于记录需要忽略的服务。

@frameworks\native\cmds\dumpsys\dumpsys.cppint Dumpsys::main(int argc, char* const argv[]) {    ...    for (int i = optind; i < argc; i++) {    if (skipServices) {        skippedServices.add(String16(argv[i]));//配置待忽略的服务    } else {        ...    }    ...}
5.3.3.3 获取支持服务列表

        dumpsys通过ServiceManager获取支持的服务集合,并排序

@frameworks\native\cmds\dumpsys\dumpsys.cppint Dumpsys::main(int argc, char* const argv[]) {    ...    if (services.empty() || showListOnly) {        services = listServices(priorityFlags, asProto);        setServiceArgs(args, asProto, priorityFlags);    }    ...}Vector Dumpsys::listServices(int priorityFilterFlags, bool filterByProto) const {    Vector services = sm_->listServices(priorityFilterFlags);//通过sm获取服务集合    services.sort(sort_func);//集合排序    ...    return services;}
5.3.3.4 打印支持服务列表

        在获取了服务集合后,会先检查服务是否存在,接着打印服务的名称,且如果当前指令设置了"-l"参数,仅打印服务集合,即流程结束。

@frameworks\native\cmds\dumpsys\dumpsys.cppint Dumpsys::main(int argc, char* const argv[]) {    ...    const size_t N = services.size();//获取支持的服务个数    if (N > 1 || showListOnly) {        // first print a list of the current services        std::cout << "Currently running services:" << std::endl;        for (size_t i=0; i service = sm_->checkService(services[i]);//检查服务状态            if (service != nullptr) {                bool skipped = IsSkipped(skippedServices, services[i]);                std::cout << "  " << services[i] << (skipped ? " (skipped)" : "") << std::endl;//打印服务名称            }        }    }    if (showListOnly) {//如果指令仅需要打印服务集合,则结束。        return 0;    }    ...}
5.3.3.5 打印目标服务

        先遍历所有需要打印的服务,如果参数有指定服务名,即N为对应服务的数量,否则N为所有支持的服务数量。接着,开启线程,通过servicemanager调用远端的dump函数,利用管道和poll机制监听远端数据。最后如果超时或者dump结束,则关闭线程,释放相关资源。

@frameworks\native\cmds\dumpsys\dumpsys.cppint Dumpsys::main(int argc, char* const argv[]) {    ...    for (size_t i = 0; i < N; i++) {        const String16& serviceName = services[i];        if (IsSkipped(skippedServices, serviceName)) continue;//跳过部分服务        if (startDumpThread(type, serviceName, args) == OK) {//step 1.创建dump打印的线程            ...            std::chrono::duration elapsedDuration;            size_t bytesWritten = 0;            status_t status =                writeDump(STDOUT_FILENO, serviceName, std::chrono::milliseconds(timeoutArgMs),                          asProto, elapsedDuration, bytesWritten);//step 2.dump执行打印操作            if (status == TIMED_OUT) {//打印超时                std::cout << std::endl                     << "*** SERVICE '" << serviceName << "' DUMP TIMEOUT (" << timeoutArgMs                     << "ms) EXPIRED ***" << std::endl                     << std::endl;            }            ...            bool dumpComplete = (status == OK);            stopDumpThread(dumpComplete);//step 3.结束dump打印线程        }    }    ...}

step 1. 创建dumpsys打印线程
        创建了一条管道,接着开启了一个线程,通过ServiceManager对象读取目标服务的dump函数,即dump打印数据。

@frameworks\native\cmds\dumpsys\dumpsys.cppstatus_t Dumpsys::startDumpThread(Type type, const String16& serviceName,      const Vector<String16>& args) {    sp<IBinder> service = sm_->checkService(serviceName);//通过SM获取service对象    int sfd[2];    if (pipe(sfd) != 0) {//创建管道,用于读取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;}

step 2. dumpsys打印到终端
        通过poll机制用来监听管道的数据,并将读取到的dump数据,打印至控制台。同时,通过计算剩余的时间,来判断当前是否读取超时。

@frameworks\native\cmds\dumpsys\dumpsys.cppstatus_t Dumpsys::writeDump(int fd, const String16& serviceName, std::chrono::milliseconds timeout,bool asProto, std::chrono::duration& elapsedDuration,size_t& bytesWritten) const {    ...    int serviceDumpFd = redirectFd_.get();    struct pollfd pfd = {.fd = serviceDumpFd, .events = POLLIN};    while (true) {        ...        int rc = TEMP_FAILURE_RETRY(poll(&pfd, 1, time_left_ms()));//poll机制检测管道数据        if (rc < 0) {           ...        } else if (rc == 0 || time_left_ms() == 0) {            status = TIMED_OUT;//计算剩余时间,来决定是否超时            break;        }        char buf[4096];        rc = TEMP_FAILURE_RETRY(read(redirectFd_.get(), buf, sizeof(buf)));//读取远端的数据        ...        if (!WriteFully(fd, buf, rc)) {//打印至控制台            ...            break;        }        totalBytes += rc;    }    ...    return status;}

step 3. 关闭dumpsys打印线程
        将dumpsys打印的线程detach掉,相关的fd句柄reset掉,释放资源。

六、dumpsys的应用

        如后续有什么应用dumpsys,或者有助于日常开发调试的场景,再补充,未完待续。

6.1 dumpsys常用指令

服务名类名指令功能
activityActivityManagerService获取某个应用的Activity信息:
adb shell dumpsys activity a packagename
获取某个应用的Service信息:
adb shell dumpsys activity s packagename
获取某个应用的Broadcast信息:
adb shell dumpsys activity b packagename
获取某个应用的Provider信息:
adb shell dumpsys activity prov packagename
获取某个应用的进程状态:
adb shell dumpsys activity p packagename
获取当前界面的Activity信息:
adb shell dumpsys activity top | grep ACTIVITY
AMS相关信息
packagePackageManagerServiceadb shell dumpsys packagePMS相关信息
windowWindowManagerServiceadb shell dumpsys windowWMS相关信息
inputInputManagerServiceadb shell dumpsys inputIMS相关信息
powerPowerManagerServiceadb shell dumpsys powerPMS相关信息
batterystatsBatterystatsServiceadb shell dumpsys batterystats电池统计信息
batteryBatteryServiceadb shell dumpsys battery电池信息
alarmAlarmManagerServiceadb shell dumpsys alarm闹钟信息
dropboxDropboxManagerServiceadb shell dumpsys dropbox调试相关
procstatsProcessStatsServiceadb shell dumpsys procstats进程统计
cpuinfoCpuBinderadb shell dumpsys cpuinfoCPU
meminfoMemBinderadb shell dumpsys meminfo内存
gfxinfoGraphicsBinderadb shell dumpsys gfxinfo图像
dbinfoDbBinderadb shell dumpsys dbinfo数据库

七、参考资料

dumpsys指令介绍:
https://developer.android.google.cn/studio/command-line/dumpsys?hl=zh-cn
管道:
Https://www.cnblogs.com/naray/p/15365954.html
Binder:
https://blog.csdn.net/shenxiaolinil/article/details/128972302

来源地址:https://blog.csdn.net/u013320490/article/details/134008928

--结束END--

本文标题: Android dumpsys介绍

本文链接: https://lsjlt.com/news/457166.html(转载时请注明来源链接)

有问题或投稿请发送至: 邮箱/279061341@qq.com    QQ/279061341

猜你喜欢
  • Android dumpsys介绍
    文章目录 一、需求二、环境三、相关概念3.1 dumpsys3.2 Binder3.3 管道 四、dumpsys指令的使用4.1 dumpsys使用4.2 dumpsys指令语法 五、...
    99+
    2023-10-26
    1024程序员节
  • Android中dumpsys命令用法简单介绍
    在Android手机上, 通过使用adb shell命令可以进入android系统的shell, 该shell除支持一些常用的标准命令之外,还支持一些和android系统相关的...
    99+
    2022-06-06
    Android
  • Android RIL介绍
    文章目录 一、需求二、相关概念2.1 IMS2.2 Volte2.3 CS域与PS域2.3.1 CS域2.3.2 PS域 2.4 VOIP2.5 URC消息2.6 HIDL 三、环境...
    99+
    2023-09-29
    android 开发语言 java
  • Android中的dumpsys命令详解
    目录一、dumpsys命令介绍1.命令说明2.系统服务查询二、包信息查询三、activity信息查询四、网络信息查询五、其他常用服务信息查询一、dumpsys命令介绍 1.命令说明 ...
    99+
    2024-04-02
  • Android OpenGl 介绍(一)
    一、OpenGl 介绍 看到这个介绍,相信大家都不会陌生,因为在平时的工作中,或多或少大家都会听说过 openGl 这个东西,而且对它的印象基本都是觉得比较高深难懂。其实这个东西也不是那么难,那么无从下手,首先必须要了解一些基本的背景和搞懂...
    99+
    2023-09-01
    android 实时音视频
  • Android中的dumpsys命令怎么用
    这篇文章主要介绍“Android中的dumpsys命令怎么用”的相关知识,小编通过实际案例向大家展示操作过程,操作方法简单快捷,实用性强,希望这篇“Android中的dumpsys命令怎么用”文章能帮助大家解决问题。一、dumpsys命令介...
    99+
    2023-06-30
  • Android录屏 MediaRecorder介绍
    Android录屏 MediaRecorder介绍 Android录屏的三种方案 1、adb shell命令screenrecord 2、Med...
    99+
    2022-06-06
    mediarecorder Android
  • Android Bitmap详细介绍
    代码如下: package com.testbitmapscale; import java.io.File; import java.io.FileInputStream;...
    99+
    2022-06-06
    bitmap Android
  • android AsyncTask详细介绍
    AsyncTask和Handler对比 1 ) AsyncTask实现的原理,和适用的优缺点 AsyncTask,是android提供的轻量级的异步类,可以直接继承AsyncT...
    99+
    2022-06-06
    asynctask Android
  • android CursorLoader用法介绍
    工作内容集中到Contact模块,这个应用查询数据的地方很多,其使用了CursorLoader这个工具大大简化了代码复杂度。android自3.0提供了Loader机制,当时g...
    99+
    2022-06-06
    Android
  • Android Socket 简单介绍
    文章目录 前言一、Socket是什么?百度百科的解释我自己的理解 二、简单示例1.服务端2.客户端3.布局4.实现 参考总结 前言 最近需求需要使用Socket进行通讯,我在工作...
    99+
    2023-09-23
    android
  • Android WorkManager使用介绍
    一、引言   WorkManager 是google提供的异步执行任务的管理框架,是 Android Jetpack 的一部分,会根据手机的API版本和应用程序的状态来选择适当的方式执行任务。   在...
    99+
    2023-09-07
    android
  • Android ViewBinding使用介绍
    目录一、kotlin-android-extensions二、ViewBinding使用1.gradle配置2.在Activity 使用3.在Fragment使用4.在Adapter...
    99+
    2024-04-02
  • android之ContentResolver与ContentProvider介绍
    android中对数据操作包含有: file, sqlite3, Preferences, ContectResolver与ContentProvider前三种数据操作方式都...
    99+
    2022-06-06
    Android
  • Android View Binding使用介绍
    前言 Android Studio稳定版发布了3.6版本,带来了一些新变化:首先外观,启动页变了,logo改了,更显现代化;增加Multi Pr...
    99+
    2022-06-06
    view Android
  • Android Thread 介绍与实例
    Android中很重要的一个机制就是线程+消息,当然线程并不是android独有的,下面,简单的说说使用线程的时候应该注意的地方 我们采用最简单的方法来建立一个android的...
    99+
    2022-06-06
    Android
  • Android Handler的详细介绍
    Handler的定义  主要接受子线程发送的数据, 并用此数据配合主线程更新UI.  解释: 当应用程序启动时,Android首先会开启一个主线程 (也就是UI线程) , 主线...
    99+
    2022-06-06
    handler Android
  • android WebView加载html5介绍
    Android设备多分辨率的问题 Android浏览器默认预览模式浏览 会缩小页面 WebView中则会以原始大小显示 Android浏览器和WebView默认为mdpi。hd...
    99+
    2022-06-06
    HTML webview HTML5 Android
  • Android WebView预渲染介绍
    目录前言术语对齐客户端可以从哪些方面优化h5页面的加载速度?优化思路预渲染的基本实现逻辑是怎样的?预创建预创建个数预创建时机预创建复用预渲染预渲染时机预渲染有效性校验时间有效性状态有...
    99+
    2024-04-02
  • Android中BinderIPC机制介绍
    目录前言一、Binder是什么?二、为什么要使用Binder三、IPC机制原理传统IPC机制如何实现跨进程通信Binder IPC机制原理小结前言 记得刚开始做Andorid那会,面...
    99+
    2024-04-02
软考高级职称资格查询
编程网,编程工程师的家园,是目前国内优秀的开源技术社区之一,形成了由开源软件库、代码分享、资讯、协作翻译、讨论区和博客等几大频道内容,为IT开发者提供了一个发现、使用、并交流开源技术的平台。
  • 官方手机版

  • 微信公众号

  • 商务合作