dumpsys源码流程

前言:看AMS和WMS的相关状态,这个命令十分有用,不止是这两个服务,其他系统级别的服务均能用该命令去dump出来重要信息,而且我们自己实现的服务,只要添加到了ServiceManager中可查询到,而且复写了Binder的dump()函数,均可以像源码一样dump出来我们想要的信息,所以对这套流程很有兴趣,因此看了dumpsys的代码实现流程,记录下来。

  1.dumpsys的用法

    简单说一下dumpsys的用法,就是用来dump系统级别的service的某个时刻的关键信息,帮助我们debug用的,可以先使用命令:dumpsys -l,去查询我们能去dump的所有服务,这里以AMS为例子,它在ServiceManager中的名字为activity,所以使用dumpsys activity便可,同理,其他service的dump方法也是一样的。由于某些service的信息量比较庞大,比如AMS的信息量就极其庞大,所以我们可以narrow down一下查询信息,比如用dumpsys activity a或者dumpsys activity activities,去查询所有activity的信息,而忽略诸如广播注册等信息,这样可以帮助我们只关注我们想要的信息。

  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进程起来的时候是在开机流程中,init进程里面实例化的。命令的处理主要逻辑在frameworks/native/cmds/dumpsys/dumpsys.cpp里的main()函数当中,截取其中的重要部分:

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

}

}

    主要是启动一个线程去执行某个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;

}

  在新起的线程中,执行某个service的dump函数,如此我们就只要看某个service的dump函数实现就好了,注意我们这些处理逻辑目前都是在native层,但是我们知道安卓是建立在Binder通信的CS架构,该dump()函数的声明是在Binder类中的,也就是我们需要找到服务端的dump()函数的真正实现哪里,如果是dumpsys activity a,那么真正实现是在java层的ActivityManagerService中,其他服务同理,当然在native层实现该dump()函数也是ok的,这个并不重要。以dumpsys activity a为例,到目前为止,我们已经解析完了dumpsys activity的含义,就是调用AMS的dump()函数,那么后面的参数 a 呢?答案需要在AMS的dump函数中找:

@Override

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

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

}

  最终会调用到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);

           }

  该函数还会解析其他的参数,具体可在该函数中看,或者使用dumpsys activity -h可以查询到所有支持的参数以及它们的含义,dumpsys activity a的全部含义就是调用到ActivityTaskManagerService的dump函数,它会遍历内部结构,把重要信息全部输出到console上,具体可见ATMS的dumpActivitiesLocked()函数是如何把信息全部打印出来的。

  至此,主要代码流程就走完了,dumpsys的其他命令也是走的一样的流程,我们可以在此基础上加入自己的逻辑,使其能dump出来我们需要的信息,注意不要跟现有的命令参数同名就好。

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

推荐阅读更多精彩内容