dumpsys 使用与源码

1-dumpsys 使用
命令格式:
adb shell dumpsys activity [options] [WHAT]

option 参数:

options 含义
-a 包括所有可用 Servier 状态
-c 包括 Client 状态,即 App 端情况
-p PACKAGE 限定输出指定包名

WHAT 参数:

WHAT 解释 对应源码
a[ctivities] activity状态 dumpActivitiesLocked()
b[roadcasts] [PACKAGE_NAME] broadcast状态 dumpBroadcastsLocked()
s[ervices] [COMP_SPEC …] service状态 newServiceDumperLocked().dumpLocked
prov[iders] [COMP_SPEC …] content provider状态 dumpProvidersLocked()
p[rocesses] [PACKAGE_NAME] 进程状态 dumpProcessesLocked()
o[om] 内存管理 dumpOomLocked()
i[ntents] [PACKAGE_NAME] pending intent状态 dumpPendingIntentsLocked()
r[ecents] 最近activity dumpRecentsLocked()
perm[issions] URI授权情况 dumpPermissionsLocked()
all 所有activities信息 dumpActivity()
top 顶部activity信息 dumpActivity()
package package相关信息 dump()

重要的服务:

服务名 类名 功能
activity ActivityManagerService AMS相关信息
package PackageManagerService PMS相关信息
window WindowManagerService WMS相关信息
input InputManagerService IMS相关信息
power PowerManagerService PMS相关信息
batterystats BatterystatsService 电池统计信息
battery BatteryService 电池信息
alarm AlarmManagerService 闹钟信息
dropbox DropboxManagerService 调试相关
procstats ProcessStatsService 进程统计
cpuinfo CpuBinder CPU
meminfo MemBinder 内存
gfxinfo GraphicsBinder 图像
dbinfo DbBinder 数据库

其他重要服务:

服务名 功能
SurfaceFlinger 图像相关
appops app使用情况
permission 权限
processinfo 进程服务
batteryproperties 电池相关
audio 查看声音信息
netstats 查看网络统计信息
diskstats 查看空间free状态
jobscheduler 查看任务计划
wifi wifi信息
diskstats 磁盘情况
usagestats 用户使用情况
devicestoragemonitor 设备信息

指令:

adb shell dumpsys activity
adb shell dumpsys activity intents    //主要输出 PendingIntentRecord
adb shell dumpsys activity broadcasts 
adb shell dumpsys activity providers
adb shell dumpsys activity permissions
adb shell dumpsys activity services
adb shell dumpsys activity recents
adb shell dumpsys activity activities
adb shell dumpsys activity processes
adb shell dumpsys activity top
adb shell dumpsys activity oom //查看进程状态
adb shell dumpsys activity activities   //输出任务栈
adb shell dumpsys meminfo <package name> //查询内存情况
adb shell dumpsys package  <package name>
adb shell dumpsys window //查询WMS服务相关信息
adb shell dumpsys cpuinfo //查询CPU情况
adb shell dumpsys -l   //可以dump的 service
adb shell service list    //可以看到所有的service
//重要的指令
adb shell dumpsys activity top |grep mResumed=true -C 10
adb shell dumpsys activity s com.example.helloworld  //查询某个App所有service状态
adb shell dumpsys activity a com.example.helloworld  //查询某个App的所有Activity状态
adb shell dumpsys activity p com.example.helloworld  //查询某个App的进程状态

举个例子:
adb shell dumpsys activity p com.example.helloworld

ACTIVITY MANAGER RUNNING PROCESSES (dumpsys activity processes)
  All known processes:
  *APP* UID 10070 ProcessRecord{3ab962e 8727:com.example.helloworld/u0a70}
    user #0 uid=10070 gids={50070, 20070, 9997}
    requiredAbi=arm64-v8a instructionSet=null
    dir=/data/app/com.example.helloworld-MVDRQ1v8KVafsDRbTEH_HA==/base.apk publicDir=/data/app/com.example.helloworld-MVDRQ1v8KVafsDRbTEH_HA==/base.apk data=/data/user/0/com.example.helloworld
    packageList={com.example.helloworld}
    compat={560dpi}
    thread=android.app.IApplicationThread$Stub$Proxy@cb84feb
    pid=8727 starting=false
    lastActivityTime=-56s649ms lastPssTime=-38s529ms nextPssTime=+1m21s429ms
    adjSeq=18860 lruSeq=0 lastPss=75MB lastSwapPss=0.00 lastCachedPss=31MB lastCachedSwapPss=0.00
    cached=false empty=false
    oom: max=1001 curRaw=0 setRaw=0 cur=0 set=0
    curSchedGroup=2 setSchedGroup=2 systemNoUi=false trimMemoryLevel=0
    curProcState=2 repProcState=2 pssProcState=2 setProcState=2 lastStateTime=-2h44m52s244ms
    hasShownUi=true pendingUiClean=true hasAboveClient=false treatLikeActivity=false
    reportedInteraction=true time=-56s650ms
    hasClientActivities=false foregroundActivities=true (rep=true)
    lastRequestedGc=-2h47m10s361ms lastLowMemory=-2h47m10s361ms reportLowMemory=false
    Activities:
      - ActivityRecord{a06206e u0 com.example.helloworld/.MainActivity t13}
    Connected Providers:
      - 922a9b5/com.android.providers.settings/.SettingsProvider->8727:com.example.helloworld/u0a70 s1/1 u0/0 +2h47m10s322ms

  UID states:
    UID u0a70: UidRecord{d6525cf u0a70 TOP  procs:1 seq(0,0,0)}

  UID validation:
    UID u0a70: UidRecord{d95d148 u0a70 TOP  procs:0 seq(0,0,0)}

  Process LRU list (sorted by oom_adj, 35 total, non-act at 3, non-svc at 3):
    Proc # 0: fore  T/A/TOP  trm: 0 8727:com.example.helloworld/u0a70 (top-activity)

  PID mappings:
    PID #8727: ProcessRecord{3ab962e 8727:com.example.helloworld/u0a70}
  mPreviousProcessVisibleTime: +6h44m56s167ms
  mConfigWillChange: false
  mDeviceIdleWhitelist=[1000, 1001, 2000, 10008, 10013]
  mDeviceIdleTempWhitelist=[]
  mVrController=[VrState=0x0,VrRenderThreadTid=0]

对应的source code
frameworks/base/services/core/java/com/android/server/am/ActivityManagerService.java

void dumpProcessesLocked(FileDescriptor fd, PrintWriter pw, String[] args,
            int opti, boolean dumpAll, String dumpPackage) {
        boolean needSep = false;
        boolean printedAnything = false;
        int numPers = 0;
        //在dumpsys 指令中,这个数据被dump 出来了
        pw.println("ACTIVITY MANAGER RUNNING PROCESSES (dumpsys activity processes)");

        if (dumpAll) {
            final int NP = mProcessNames.getMap().size();
            for (int ip=0; ip<NP; ip++) {
                SparseArray<ProcessRecord> procs = mProcessNames.getMap().valueAt(ip);
                final int NA = procs.size();
                for (int ia=0; ia<NA; ia++) {
                    ProcessRecord r = procs.valueAt(ia);
                    if (dumpPackage != null && !r.pkgList.containsKey(dumpPackage)) {
                        continue;
                    }
                    if (!needSep) {
                        pw.println("  All known processes:");
                        needSep = true;
                        printedAnything = true;
                    }
                    pw.print(r.persistent ? "  *PERS*" : "  *APP*");
                        pw.print(" UID "); pw.print(procs.keyAt(ia));
                        pw.print(" "); pw.println(r);
                    r.dump(pw, "    ");
                    if (r.persistent) {
                        numPers++;
                    }
                }
            }
        }
.......

2-dumpsys 源码介绍
frameworks/native/cmds/dumpsys/Android.bp

cc_defaults {
    name: "dumpsys_defaults",
    cflags: [
        "-Wall",
        "-Werror",
    ],
    srcs: [
        "dumpsys.cpp",
    ],

    shared_libs: [
        "libbase",
        "libutils",
        "liblog",
        "libbinder",
    ],
    clang: true,
}

//
// Static library used in testing and executable
//

cc_library_static {
    name: "libdumpsys",
    defaults: ["dumpsys_defaults"],
    export_include_dirs: ["."],
}

//
// Executable
//
cc_binary {
    name: "dumpsys",
    defaults: ["dumpsys_defaults"],
    srcs: [
        "main.cpp",
    ],
}
subdirs = ["tests"]

main.cpp 可以看出main 就是defaultServiceManager, 根据参数获取对应的service

int main(int argc, char* const argv[]) {
    signal(SIGPIPE, SIG_IGN);
    sp<IServiceManager> sm = defaultServiceManager();
    fflush(stdout);
    if (sm == nullptr) {
        ALOGE("Unable to get default service manager!");
        aerr << "dumpsys: Unable to get default service manager!" << endl;
        return 20;
    }

    Dumpsys dumpsys(sm.get());
    return dumpsys.main(argc, argv);
}

frameworks/native/cmds/dumpsys/dumpsys.cpp

static int sort_func(const String16* lhs, const String16* rhs)
{
    return lhs->compare(*rhs);
}
//使用说明
static void usage() {
    fprintf(stderr,
        "usage: dumpsys\n"
            "         To dump all services.\n"
            "or:\n"
            "       dumpsys [-t TIMEOUT] [--help | -l | --skip SERVICES | SERVICE [ARGS]]\n"
            "         --help: shows this help\n"
            "         -l: only list services, do not dump them\n"
            "         -t TIMEOUT: TIMEOUT to use in seconds instead of default 10 seconds\n"
            "         --skip SERVICES: dumps all services but SERVICES (comma-separated list)\n"
            "         SERVICE [ARGS]: dumps only service SERVICE, optionally passing ARGS to it\n");
}

static bool IsSkipped(const Vector<String16>& skipped, const String16& service) {
    for (const auto& candidate : skipped) {
        if (candidate == service) {
            return true;
        }
    }
    return false;
}

int Dumpsys::main(int argc, char* const argv[]) {
    Vector<String16> services;
    Vector<String16> args;
    Vector<String16> skippedServices;
    bool showListOnly = false;
    bool skipServices = false;
    int timeoutArg = 10;
    static struct option longOptions[] = {
        {"skip", no_argument, 0,  0 },
        {"help", no_argument, 0,  0 },
        {     0,           0, 0,  0 }
    };

    // Must reset optind, otherwise subsequent calls will fail (wouldn't happen on main.cpp, but
    // happens on test cases).
    optind = 1;
    while (1) {
        int c;
        int optionIndex = 0;

        c = getopt_long(argc, argv, "+t:l", longOptions, &optionIndex);

        if (c == -1) {
            break;
        }

        switch (c) {
        case 0:
            if (!strcmp(longOptions[optionIndex].name, "skip")) {
                skipServices = true;   //携带的参数skip
            } 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':
            showListOnly = true;
            break;

        default:
            fprintf(stderr, "\n");
            usage();
            return -1;
        }
    }

    for (int i = optind; i < argc; i++) {
        if (skipServices) {
            skippedServices.add(String16(argv[i]));
        } else {
            if (i == optind) {
                services.add(String16(argv[i]));   //把service 添加services
            } else {
                args.add(String16(argv[i]));
            }
        }
    }

    if ((skipServices && skippedServices.empty()) ||
            (showListOnly && (!services.empty() || !skippedServices.empty()))) {
        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();

    if (N > 1) {
        // first print a list of the current services
        aout << "Currently running services:" << endl;

        for (size_t i=0; i<N; i++) {
            // 获取IBinder service
            sp<IBinder> service = sm_->checkService(services[i]);

            if (service != nullptr) {
                bool skipped = IsSkipped(skippedServices, services[i]);
                aout << "  " << services[i] << (skipped ? " (skipped)" : "") << endl;
            }
        }
    }

    if (showListOnly) {
        return 0;
    }

    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 != nullptr) {
            int sfd[2];

            if (pipe(sfd) != 0) {
                aerr << "Failed to create pipe to dump service info for " << service_name
                     << ": " << strerror(errno) << endl;
                continue;
            }

            unique_fd local_end(sfd[0]);
            unique_fd remote_end(sfd[1]);
            sfd[0] = sfd[1] = -1;

            if (N > 1) {
                aout << "------------------------------------------------------------"
                        "-------------------" << endl;
                aout << "DUMP OF SERVICE " << service_name << ":" << endl;
            }

            // dump blocks until completion, so spawn a thread..
            std::thread dump_thread([=, remote_end { std::move(remote_end) }]() mutable {
                //对每个service dump , dump 信息全部都在里面
                int err = service->dump(remote_end.get(), args);

                // It'd be nice to be able to close the remote end of the socketpair before the dump
                // call returns, to terminate our reads if the other end closes their copy of the
                // file descriptor, but then hangs for some reason. There doesn't seem to be a good
                // way to do this, though.
                remote_end.reset();

                if (err != 0) {
                    aerr << "Error dumping service info: (" << strerror(err) << ") " << service_name
                         << endl;
                }
            });
        ........
    }
    return 0;
}

这个指令比较简单,就是getservice dump 信息,关键是要对service 比较熟悉

1-main.cpp中defaultServiceManager()函数用来获取ServiceManager对象,并传递到dumpsys.cpp中。
2-sm_->listServices(),获取系统中所有向ServiceManager中注册过的服务。
3-如果命令加入了--skip SERVICES.则加入到skippedServices中,过滤service_name,最后sm_->checkService(service_name)用来获取指定的service。
4-最后调用service->dump()。这是最核心的方法,主要是service去掉用各自的dump()方法来获取相关dump信息。

REF:
https://developer.android.com/studio/command-line/dumpsys
//www.greatytc.com/p/436f3c592974

最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 215,723评论 6 498
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 92,003评论 3 391
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 161,512评论 0 351
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 57,825评论 1 290
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 66,874评论 6 388
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 50,841评论 1 295
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 39,812评论 3 416
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 38,582评论 0 271
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 45,033评论 1 308
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 37,309评论 2 331
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 39,450评论 1 345
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 35,158评论 5 341
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 40,789评论 3 325
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 31,409评论 0 21
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 32,609评论 1 268
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 47,440评论 2 368
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 44,357评论 2 352