dumpsys 使用與源碼

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

option 參數(shù):

options 含義
-a 包括所有可用 Servier 狀態(tài)
-c 包括 Client 狀態(tài),即 App 端情況
-p PACKAGE 限定輸出指定包名

WHAT 參數(shù):

WHAT 解釋 對(duì)應(yīng)源碼
a[ctivities] activity狀態(tài) dumpActivitiesLocked()
b[roadcasts] [PACKAGE_NAME] broadcast狀態(tài) dumpBroadcastsLocked()
s[ervices] [COMP_SPEC …] service狀態(tài) newServiceDumperLocked().dumpLocked
prov[iders] [COMP_SPEC …] content provider狀態(tài) dumpProvidersLocked()
p[rocesses] [PACKAGE_NAME] 進(jìn)程狀態(tài) dumpProcessesLocked()
o[om] 內(nèi)存管理 dumpOomLocked()
i[ntents] [PACKAGE_NAME] pending intent狀態(tài) dumpPendingIntentsLocked()
r[ecents] 最近activity dumpRecentsLocked()
perm[issions] URI授權(quán)情況 dumpPermissionsLocked()
all 所有activities信息 dumpActivity()
top 頂部activity信息 dumpActivity()
package package相關(guān)信息 dump()

重要的服務(wù):

服務(wù)名 類(lèi)名 功能
activity ActivityManagerService AMS相關(guān)信息
package PackageManagerService PMS相關(guān)信息
window WindowManagerService WMS相關(guān)信息
input InputManagerService IMS相關(guān)信息
power PowerManagerService PMS相關(guān)信息
batterystats BatterystatsService 電池統(tǒng)計(jì)信息
battery BatteryService 電池信息
alarm AlarmManagerService 鬧鐘信息
dropbox DropboxManagerService 調(diào)試相關(guān)
procstats ProcessStatsService 進(jìn)程統(tǒng)計(jì)
cpuinfo CpuBinder CPU
meminfo MemBinder 內(nèi)存
gfxinfo GraphicsBinder 圖像
dbinfo DbBinder 數(shù)據(jù)庫(kù)

其他重要服務(wù):

服務(wù)名 功能
SurfaceFlinger 圖像相關(guān)
appops app使用情況
permission 權(quán)限
processinfo 進(jìn)程服務(wù)
batteryproperties 電池相關(guān)
audio 查看聲音信息
netstats 查看網(wǎng)絡(luò)統(tǒng)計(jì)信息
diskstats 查看空間free狀態(tài)
jobscheduler 查看任務(wù)計(jì)劃
wifi wifi信息
diskstats 磁盤(pán)情況
usagestats 用戶(hù)使用情況
devicestoragemonitor 設(shè)備信息

指令:

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 //查看進(jìn)程狀態(tài)
adb shell dumpsys activity activities   //輸出任務(wù)棧
adb shell dumpsys meminfo <package name> //查詢(xún)內(nèi)存情況
adb shell dumpsys package  <package name>
adb shell dumpsys window //查詢(xún)WMS服務(wù)相關(guān)信息
adb shell dumpsys cpuinfo //查詢(xún)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  //查詢(xún)某個(gè)App所有service狀態(tài)
adb shell dumpsys activity a com.example.helloworld  //查詢(xún)某個(gè)App的所有Activity狀態(tài)
adb shell dumpsys activity p com.example.helloworld  //查詢(xún)某個(gè)App的進(jìn)程狀態(tài)

舉個(gè)例子:
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]

對(duì)應(yīng)的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 指令中,這個(gè)數(shù)據(jù)被dump 出來(lái)了
        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, 根據(jù)參數(shù)獲取對(duì)應(yīng)的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);
}
//使用說(shuō)明
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;   //攜帶的參數(shù)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 {
                //對(duì)每個(gè)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;
}

這個(gè)指令比較簡(jiǎn)單,就是getservice dump 信息,關(guān)鍵是要對(duì)service 比較熟悉

1-main.cpp中defaultServiceManager()函數(shù)用來(lái)獲取ServiceManager對(duì)象,并傳遞到dumpsys.cpp中。
2-sm_->listServices(),獲取系統(tǒng)中所有向ServiceManager中注冊(cè)過(guò)的服務(wù)。
3-如果命令加入了--skip SERVICES.則加入到skippedServices中,過(guò)濾service_name,最后sm_->checkService(service_name)用來(lái)獲取指定的service。
4-最后調(diào)用service->dump()。這是最核心的方法,主要是service去掉用各自的dump()方法來(lái)獲取相關(guān)dump信息。

REF:
https://developer.android.com/studio/command-line/dumpsys
http://m.itdecent.cn/p/436f3c592974

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
【社區(qū)內(nèi)容提示】社區(qū)部分內(nèi)容疑似由AI輔助生成,瀏覽時(shí)請(qǐng)結(jié)合常識(shí)與多方信息審慎甄別。
平臺(tái)聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點(diǎn),簡(jiǎn)書(shū)系信息發(fā)布平臺(tái),僅提供信息存儲(chǔ)服務(wù)。

友情鏈接更多精彩內(nèi)容