25、AMS 日志与调试:logcat关键tag、dumpsys activity命令、Systrace分析

做Android Framework开发,说白了就是跟各种疑难杂症打交道。Activity启动闪退?应用无响应?页面跳转卡顿?这些问题,十有八九都得靠日志和调试工具来定位。今天我就把压箱底的调试三板斧拿出来聊聊——logcat、dumpsys、Systrace。这三样东西用好了,能省你大半的排查时间。

25.1 logcat 关键Tag:从海量日志里捞针

logcat每天能刷出几万行日志,但真正有用的就那么几个Tag。我个人习惯,先把不相关的过滤掉,只盯着AMS相关的Tag看。

Tag 优先级 说明
ActivityManager I / W / E Activity生命周期、启动流程、ANR信息
WindowManager I / W 窗口焦点变化、窗口添加/移除
InputDispatcher I / W / E 触摸事件分发、ANR触发点
SystemServer I / W AMS启动过程、服务注册
PackageManager I / W 应用安装、权限检查

举个例子,Activity启动失败时,你会在logcat里看到类似这样的信息:

// 启动Activity时AMS的关键日志
I ActivityManager: START u0 {act=android.intent.action.MAIN cat=[android.intent.category.LAUNCHER] flg=0x10200000 cmp=com.example.app/.MainActivity} from uid 1000
I ActivityManager: Start proc 12345:com.example.app/u0a123 for activity {com.example.app/.MainActivity}
W ActivityManager: Activity pause timeout for ActivityRecord{xxx}
E ActivityManager: ANR in com.example.app (com.example.app/.MainActivity)

你看,从START到Start proc,再到pause timeout,最后ANR,每一步都有日志。我曾经遇到过一个诡异的问题:Activity启动后黑屏,但logcat里没有任何错误。后来我加了WindowManager的Tag一看,发现窗口焦点根本没切过去——原来是上一个Activity的onPause里做了耗时操作,把主线程卡住了。

我的小技巧:调试AMS问题时,我习惯同时开三个logcat窗口。一个只过滤ActivityManager,一个看WindowManager,一个看System.err。这样能同时追踪流程和异常,效率高很多。

25.2 dumpsys activity:系统状态的X光机

logcat看的是过程,dumpsys看的是状态。你想想看,当Activity启动失败时,你总得知道当前系统里到底有哪些Activity、它们是什么状态吧?dumpsys activity就是干这个的。

我最常用的几个子命令:

  • dumpsys activity activities —— 查看所有ActivityRecord,包括栈信息、状态、intent
  • dumpsys activity processes —— 查看所有进程信息,包括oom_adj、pid、uid
  • dumpsys activity services —— 查看已绑定的Service列表
  • dumpsys activity broadcasts —— 查看广播接收器注册情况

输出内容长什么样?我截取一段实际调试时的输出:

ACTIVITY MANAGER ACTIVITIES (dumpsys activity activities)
  Display #0 (activities from top to bottom):
    Stack #1:
      Task id #123
        * Hist #0: ActivityRecord{xxx u0 com.example.app/.MainActivity t123}
            Intent: {act=android.intent.action.MAIN cat=[android.intent.category.LAUNCHER]}
            ProcessRecord: xxx (pid 12345)
            State: RESUMED
            WindowState: ADDED_AT (visible)

这里的信息量很大。State是RESUMED说明Activity在前台,WindowState是ADDED_AT说明窗口已经添加。如果State是PAUSING或者STOPPING,那说明切换流程卡住了。我遇到过好几次,Activity跳转后黑屏,dumpsys一看State是PAUSING,再配合logcat的pause timeout日志,问题就锁定了——是上一个Activity的onPause里做了网络请求。

注意:dumpsys activity的输出内容非常长,尤其是activities子命令。我建议先grep过滤关键字段,比如dumpsys activity activities | grep -E "State|pid|Stack"。别傻乎乎地从头看到尾,那会累死。

25.3 Systrace分析:把时间线画出来

logcat和dumpsys能告诉你发生了什么,但很难告诉你「为什么这么慢」。Systrace就不一样了,它把系统里每个线程、每个方法调用都按时间线画出来。说白了,就是给系统做了一次心电图。

我一般这样用Systrace:

  1. 先确定要追踪的场景,比如「点击图标到Activity显示」
  2. python systrace.py -t 10 -o trace.html am wm gfx input view抓取10秒
  3. 在生成的HTML里找到对应的区间,看每个阶段花了多少时间

一个典型的Activity启动流程,在Systrace里会看到这些阶段:

  • handleLaunchActivity —— AMS开始处理启动请求
  • bindApplication —— 绑定应用进程
  • activityStart —— ActivityThread开始启动
  • onCreate / onStart / onResume —— 生命周期回调
  • performTraversals —— 第一次布局和绘制

我记得有一次,用户反馈某个页面打开特别慢。用Systrace一看,onCreate里有个数据库查询花了800ms,而performTraversals只用了16ms。问题就很清楚了——不是渲染慢,是数据准备慢。后来把查询放到异步线程,启动时间从1.2秒降到了400ms。

核心思路:Systrace的关键不是看「有没有报错」,而是看「时间花在哪了」。我建议重点关注两个指标:一是主线程上有没有超过16ms的连续任务(掉帧),二是AMS和App进程之间的Binder调用耗时。

25.4 三件套配合使用:一个实战案例

光说理论没意思,我拿一个真实案例串一下。有一次线上反馈,某款应用在低端机上启动后白屏5秒才显示内容。

第一步,我先用logcat过滤ActivityManager:

I ActivityManager: Displayed com.example.app/.MainActivity: +3s200ms

嗯?Displayed时间只有3.2秒,但用户说白屏5秒。说明问题不在AMS的启动流程里,而在后面的渲染阶段。

第二步,用dumpsys activity activities看看窗口状态:

State: RESUMED
WindowState: ADDED_AT (visible)

窗口已经可见了,但用户看到的是白屏。那问题大概率出在SurfaceFlinger或者GPU合成上。

第三步,抓Systrace,重点看performTraversals和doFrame。结果发现:

  • performTraversals只用了12ms,正常
  • 但doFrame里有一个Choreographer#doFrame的间隔达到了4.8秒
  • 点进去一看,是主线程在等一个CountDownLatch,而那个锁在子线程里被一个网络请求卡住了

问题就水落石出了——子线程的网络请求超时,导致主线程的锁等待,虽然Activity已经显示,但UI线程被阻塞,无法处理后续的绘制指令。用户看到的就是白屏。

我的经验:调试这类问题,千万别只依赖一种工具。logcat告诉你「发生了什么」,dumpsys告诉你「当前状态」,Systrace告诉你「时间去哪了」。三样东西互相印证,才能快速定位根因。

25.5 知识体系总览

下面这张图是我自己总结的AMS调试知识体系,你可以把它当成一个快速索引。遇到问题时,先看属于哪个层面,再选对应的工具。

AMS 调试三板斧 logcat 过程追踪 • ActivityManager Tag • WindowManager Tag • InputDispatcher Tag • 过滤技巧 • 优先级控制 • 时间戳对齐 • 关键词搜索 适用:启动失败、ANR、崩溃 dumpsys activity 状态快照 • activities 子命令 • processes 子命令 • services 子命令 • broadcasts 子命令 • ActivityRecord 状态 • WindowState 信息 • oom_adj 查看 适用:状态异常、进程优先级 Systrace 时间线分析 • 启动流程追踪 • 主线程耗时分析 • Binder调用耗时 • 掉帧检测 • 锁竞争分析 • 自定义Trace • 阶段耗时对比 适用:性能瓶颈、卡顿、白屏 三者配合:logcat 定位问题 → dumpsys 确认状态 → Systrace 分析耗时

嗯,这套调试方法我用了好多年,从Android 4.4到现在的Android 14,核心思路一直没变。你只要把这三样工具练熟了,大部分AMS相关的问题都能在半小时内定位到根因。剩下的,就是修代码的事了。


公众号:蓝海资料掘金营,微信deep3321