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