dumpsys源碼流程

前言:看AMS和WMS的相關(guān)狀態(tài),這個(gè)命令十分有用,不止是這兩個(gè)服務(wù),其他系統(tǒng)級別的服務(wù)均能用該命令去dump出來重要信息,而且我們自己實(shí)現(xiàn)的服務(wù),只要添加到了ServiceManager中可查詢到,而且復(fù)寫了Binder的dump()函數(shù),均可以像源碼一樣dump出來我們想要的信息,所以對這套流程很有興趣,因此看了dumpsys的代碼實(shí)現(xiàn)流程,記錄下來。

? 1.dumpsys的用法

? ? 簡單說一下dumpsys的用法,就是用來dump系統(tǒng)級別的service的某個(gè)時(shí)刻的關(guān)鍵信息,幫助我們debug用的,可以先使用命令:dumpsys -l,去查詢我們能去dump的所有服務(wù),這里以AMS為例子,它在ServiceManager中的名字為activity,所以使用dumpsys activity便可,同理,其他service的dump方法也是一樣的。由于某些service的信息量比較龐大,比如AMS的信息量就極其龐大,所以我們可以narrow down一下查詢信息,比如用dumpsys activity a或者dumpsys activity activities,去查詢所有activity的信息,而忽略諸如廣播注冊等信息,這樣可以幫助我們只關(guān)注我們想要的信息。

? 2.代碼邏輯

? ? 我們以dumpsys activity a這句命令為例去了解流程。frameworks/native/cmds/dumpsys/main.cpp,該目錄是framework處理dumpsys命令的入口:

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!");

? ? ?? std::cerr << "dumpsys: Unable to get default service manager!" << std::endl;

? ? ?? return 20;

?? }

?? Dumpsys dumpsys(sm.get());

?? return dumpsys.main(argc, argv);

}

? 如果ServiceManager還沒起來,無法處理命令,所以需要判空,SM進(jìn)程起來的時(shí)候是在開機(jī)流程中,init進(jìn)程里面實(shí)例化的。命令的處理主要邏輯在frameworks/native/cmds/dumpsys/dumpsys.cpp里的main()函數(shù)當(dāng)中,截取其中的重要部分:

int Dumpsys::main(int argc, char* const argv[]) {

if (startDumpThread(type, serviceName, args) == OK) {

?? bool addSeparator = (N > 1);

?? if (addSeparator) {

? ? ?? writeDumpHeader(STDOUT_FILENO, serviceName, priorityFlags);

?? }

?? std::chrono::duration<double> elapsedDuration;

?? size_t bytesWritten = 0;

?? status_t status =

? ? ?? writeDump(STDOUT_FILENO, serviceName, std::chrono::milliseconds(timeoutArgMs),

? ? ? ? ? ? ? ?? asProto, elapsedDuration, bytesWritten);

?? if (status == TIMED_OUT) {

? ? ?? std::cout << std::endl

? ? ? ? ? ? << "*** SERVICE '" << serviceName << "' DUMP TIMEOUT (" << timeoutArgMs

? ? ? ? ? ? << "ms) EXPIRED ***" << std::endl

? ? ? ? ? ? << std::endl;

?? }

?? if (addSeparator) {

? ? ?? writeDumpFooter(STDOUT_FILENO, serviceName, elapsedDuration);

?? }

?? bool dumpComplete = (status == OK);

?? stopDumpThread(dumpComplete);

}

}

? ? 主要是啟動一個(gè)線程去執(zhí)行某個(gè)service的dump的具體命令:

status_t Dumpsys::startDumpThread(Type type, const String16& serviceName,

? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ?? const Vector<String16>& args) {

?? sp<IBinder> service = sm_->checkService(serviceName);

?? // 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);

? ? ? ? ?? break;

?? });

?? return OK;

}

? 在新起的線程中,執(zhí)行某個(gè)service的dump函數(shù),如此我們就只要看某個(gè)service的dump函數(shù)實(shí)現(xiàn)就好了,注意我們這些處理邏輯目前都是在native層,但是我們知道安卓是建立在Binder通信的CS架構(gòu),該dump()函數(shù)的聲明是在Binder類中的,也就是我們需要找到服務(wù)端的dump()函數(shù)的真正實(shí)現(xiàn)哪里,如果是dumpsys activity a,那么真正實(shí)現(xiàn)是在java層的ActivityManagerService中,其他服務(wù)同理,當(dāng)然在native層實(shí)現(xiàn)該dump()函數(shù)也是ok的,這個(gè)并不重要。以dumpsys activity a為例,到目前為止,我們已經(jīng)解析完了dumpsys activity的含義,就是調(diào)用AMS的dump()函數(shù),那么后面的參數(shù) a 呢?答案需要在AMS的dump函數(shù)中找:

@Override

protected void dump(FileDescriptor fd, PrintWriter pw, String[] args) {

?? PriorityDump.dump(mPriorityDumper, fd, pw, args);

}

? 最終會調(diào)用到doDump():

private void doDump(FileDescriptor fd, PrintWriter pw, String[] args, boolean useProto) {

? ? ?? // Is the caller requesting to dump a particular piece of data?

? ? ?? if (opti < args.length) {

? ? ? ? ?? String cmd = args[opti];

? ? ? ? ?? opti++;

? ? ? ? ?? if (DUMP_ACTIVITIES_SHORT_CMD.equals(cmd)) {? //DUMP_ACTIVITIES_SHORT_CMD = "a"

? ? ? ? ? ? ?? mAtmInternal.dump(

? ? ? ? ? ? ? ? ? ? ?? cmd, fd, pw, args, opti, true /* dumpAll */, dumpClient, dumpPackage);

? ? ? ? ?? }

? 該函數(shù)還會解析其他的參數(shù),具體可在該函數(shù)中看,或者使用dumpsys activity -h可以查詢到所有支持的參數(shù)以及它們的含義,dumpsys activity a的全部含義就是調(diào)用到ActivityTaskManagerService的dump函數(shù),它會遍歷內(nèi)部結(jié)構(gòu),把重要信息全部輸出到console上,具體可見ATMS的dumpActivitiesLocked()函數(shù)是如何把信息全部打印出來的。

? 至此,主要代碼流程就走完了,dumpsys的其他命令也是走的一樣的流程,我們可以在此基礎(chǔ)上加入自己的邏輯,使其能dump出來我們需要的信息,注意不要跟現(xiàn)有的命令參數(shù)同名就好。

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

相關(guān)閱讀更多精彩內(nèi)容

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