Appearance
调试工具链:dumpsys、Perfetto、btsnoop、logcat 与 ANR 阅读路径
本页导读:这一页是 Framework 学习者的「实机显微镜」操作手册:dumpsys 常用清单与三大实战样例(activity/window/meminfo)、gfxinfo 帧统计与 GPU 呈现模式的历史、Perfetto 从配置到 trace 解读的最短路径、蓝牙 btsnoop 抓取与分析、ANR trace 的固定阅读顺序,外加开发者选项逐项盘点。Android 16 新增的系统触发剖析(ProfilingManager)把 ANR/冷启动现场采集官方化,放在 §九。
版本注记:命令在 Android 12–16 真机验证通用;标注「16 新增」的条目见 a16/04 §四。官方工具入口:adb、Perfetto、AOSP 图形架构。
一、adb 与 logcat:一切的地基
adb 基础(完整清单见官方 adb 文档):
bash
adb devices -l # 列设备与传输
adb shell pidof <pkg> # 拿 pid(后面多处要用)
adb bugreport bugreport.zip # 一键打包:dropbox+anr+btsnoop+dumpsys 快照全在里面logcat 姿势分格:
bash
adb logcat -v time -v color # 带时间着色
adb logcat -b crash -d # 只 dump crash buffer(-d 打印后退出)
adb logcat --pid=$(adb shell pidof com.foo) # 锁进程
adb logcat ActivityManager:V System.err: E "*": S # tag:level 白名单式过滤
adb logcat -T 300 # 只看最近 300 行,避免全量刷屏
adb logcat -b events | grep -E "am_(proc_died|anr|kill)" # 事件缓冲区:进程死亡/ANR/杀进程时间线三条习惯:① 复现问题前 logcat -c 清场;② 事件类问题先看 -b events 再看 main;③ 交付排查材料直接 bugreport,比手抄 log 完整得多。
二、dumpsys 常用清单
用法:
adb shell dumpsys <service>,加过滤看目标域。下表是框架学习+日常排查的最小集。
| 命令 | 看什么 | 高频场景 |
|---|---|---|
dumpsys activity activities | 任务栈、当前 ActivityRecord、回退栈 | 「它到底在哪个 task」「返回行为异常」 |
dumpsys activity broadcasts | 广播队列与派发计数 | 广播积压、优先级问题(配合 a16/01 §三) |
dumpsys activity recents | 最近任务 | 桌面卡片异常 |
dumpsys window windows | 窗口列表、焦点 | 焦点丢失、层级问题 |
dumpsys window displays | 显示区域、insets | edge-to-edge/刘海适配调试 |
dumpsys meminfo <pkg> | 内存 PSS/RSS 分解 | 泄漏趋势、启动内存 |
dumpsys cpuinfo | CPU 占用快照 | 发热定位第一步 |
dumpsys gfxinfo <pkg> | 帧统计 | 掉帧量化(§四) |
dumpsys gfxinfo <pkg> framestats | 最近帧逐帧数据 | 定位卡帧时间点 |
dumpsys notification | 通知记录与额度 | 通知不弹 |
dumpsys alarm | 闹钟与唤醒 | 唤醒风暴、周期任务 |
dumpsys jobscheduler | 作业状态/配额 | 作业不跑(对照 16 stop reason) |
dumpsys deviceidle | 待机分档与 Doze | 「为什么被省电杀掉」 |
dumpsys power / dumpsys batterystats | 耗电聚合 | 异常耗电归因 |
dumpsys package <pkg> | 组件/权限/签名/ABI | 权限授予态、targetSdk 实锤 |
dumpsys package modules | Mainline ApexModule 版本 | 组件版本对齐(a16/06 §九) |
dumpsys input | 输入设备与焦点窗口 | 触摸丢失 |
dumpsys SurfaceFlinger | 显示层级/layers | 合成异常(--list 更轻) |
dumpsys display | 显示模式/亮度 | 帧率模式确认(ARR) |
dumpsys media.player / dumpsys media.camera | 媒体/相机服务态 | 播放黑屏、相机占用 |
dumpsys audio / dumpsys audio_policy | 音频焦点与路由 | 无声/焦点被抢 |
dumpsys bluetooth(部分机型 bluetooth_manager) | 适配器/配对/连接态 | 蓝牙问题入口 |
dumpsys wifi | Wi-Fi 状态机 | 断连排查 |
dumpsys telephony.registry | 蜂窝/卡槽 | 双卡行为 |
dumpsys dropbox --print | 系统级事件仓库(ANR/CRASH) | 事故取证 |
dumpsys gpu | GPU 内存与驱动信息 | 图形内存异常 |
三、dumpsys 实战三例
例 1 · 谁在焦点上(输入问题第一步)
bash
adb shell dumpsys window windows | grep -E "mCurrentFocus|mFocusedApp"焦点窗口不对 → 再查 dumpsys input 的焦点分发;两处都正常仍无响应 → 走 ANR/主线程阻塞路线(§八)。
例 2 · 一个包的内存画像
bash
adb shell dumpsys meminfo com.foo读法:先看 TOTAL PSS 基线 → 操作可疑流程 → 再取一次做差;Java Heap/Native Heap/Graphics/.so mmap 四段分头记账:Graphics 涨是纹理/Surface 泄漏,.so mmap 异常是多 ABI 加载。趋势比单次绝对值有用。
例 3 · Activity 启动记录
bash
adb shell dumpsys activity activities | grep -A2 "Hist #0"看当前 task 顶部的组件、状态与 isPreRunning/uri 线索;配合 am start -W 打印的 ThisTime/TotalTime 做启动计时基线。
四、帧统计与 GPU 呈现模式:工具在换,方法没换
dumpsys gfxinfo <pkg>:历史帧直方图与 jank 计数;framestats子命令给逐帧(Intended→Reported 各阶段)。CI 里常用framestats做前后对比。- GPU 呈现模式分析(旧开发者选项曲线)已退役:那是 hwui 早期的板载曲线;现代官方路径是 Perfetto 的 frame timeline(含 Frame Pacing Monitor 数据)与 gfxinfo。老教程里「打开开发者选项看绿线」的操作在 12+ 设备上已不存在,读到就当历史。
- 16 的帧率新面:ARR 场景下「内容帧率 vs 显示刷新率」要分开看(a16/04 §三),trace 里显示模式与 frame timeline 一起读。
五、Perfetto:配置 → 抓取 → 打开,三步成环
姿势 A:图形化配置(推荐新手)——ui.perfetto.dev 的 Record new trace 流程(含 Android 板载录制预设:Sched/Gfx/Input/WM 等分类勾选)。
姿势 B:文本配置(可进 CI) config.txtpb:
text
buffers { size_kb: 131072, fill_policy: RING_BUFFER }
data_sources {
config {
name: "linux.ftrace"
ftrace_config {
atrace_categories: "sched"
atrace_categories: "gfx"
atrace_categories: "view"
atrace_categories: "wm"
atrace_categories: "am"
atrace_categories: "binder_driver"
atrace_categories: "input"
}
}
}
data_sources { config { name: "android.log" } }
duration_ms: 10000bash
adb push config.txtpb /data/local/tmp/
adb shell perfetto -c /data/local/tmp/config.txtpb -o /data/misc/perfetto-traces/t.perfetto --txt
adb pull /data/misc/perfetto-traces/t.perfetto
# 拖进 ui.perfetto.dev 打开trace 解读最短路径(应用卡顿场景):
- 定位目标进程 → 展开 主线程,圈出时间窗内最长/最意外的 Slice(
bindApplication、Choreographer#doFrame…)。 - 主线程空隙处看线程状态色带:Running 绿、Runnable(想跑没 CPU)黄、Sleeping 灰——黄多是被抢核,灰多是等锁/等 Binder。
- 展开 Binder 轨道:一次
transact拉长 → 对端进程服务慢,去对端进程继续追。 - 图形问题看 Frame timeline:
Expected/Actual线与 SurfaceFlinger 侧 vsync,超线帧即 jank;结合 CPU 频率与热轨判断是不是节流(16 应用侧可查 headroom,a16/04 §四)。 - 进阶用 Trace Processor SQL 在 UI 里直接查(
slice/thread_state虚拟表),批量问题不要肉眼数。
六、蓝牙调试:btsnoop 一条线
- 打开开发者选项「启用蓝牙 HCI 记录」(英文 HCI snoop log)。
- 复现问题。日志文件通常在
/data/misc/bluetooth/btsnoop_hci.log(路径随 OEM/版本浮动,不确定就直接adb bugreport,会自动携带 btsnoop)。 - 用 Wireshark 打开:过滤
bthci_evt(事件)、bthci_cmd(命令)、btl2cap(L2CAP 通道);配对类问题按时间找IO Capability Request/Response与Authentication Requested序列。 - 和 16 的绑定新行为对照:bond loss 场景下抓 snoop + logcat
蓝牙标签 +ACTION_KEY_MISSING广播时序,三方对齐后再下结论(a16/05 §二)。 - 隐私提醒:snoop 可能含明文空口数据(早期配对阶段),按敏感日志管理,不要进公共 issue 附件。
七、ANR:触发、取证、阅读固定动线
触发常识:ANR 不只「5 秒输入超时」——输入分发超时、前台服务未按时 start、广播超时、ContentProvider 发布超时都会触发;具体阈值以 ROM 实现为准。系统写三处证据:dropbox(事件条目)、/data/anr/(trace 文件)、logcat(ANR 前后上下文)。
取证命令:
bash
adb shell dumpsys dropbox --print | grep -A5 "system_app_anr" # 事件与摘要
adb pull /data/anr ./anr_dump # 需权限;或 bugreport 自动带出
adb shell kill -3 <pid> # 主动让 ART dump 当前线程栈(非事故,自查用)阅读固定动线(拿到 anr trace 后按序问自己):
- Subject 一行:哪种 ANR(
Input dispatching timed out/executing service…)——决定后续看哪条链。 - CPU usage / Load 段:整机是不是过载(%user/%kernel/iowait);全机忙时单应用栈未必是元凶。
- 主线程栈(
"main" tid=1):栈顶在nativePollOnce且无锁 → 大概率消息队列被上游堵或压根没收到事件;栈顶在业务锁/Binder → 直接定位。 - 锁链:
waiting to lock <addr> held by tid N顺藤摸到持锁线程栈,多数经典 ANR 死在「主线程等 IO/等 Binder」。 - Binder 段:
pending binder transactions——对端服务卡会成串挂 here。 - 时间对齐 logcat/events(进程启动、GC 风暴、Doze 进出常是剧本前半段)。
- 16+ 设备直接注册系统触发剖析拿 ANR 现场 Perfetto trace(§九),比文本栈多「事发时 CPU 在干什么」。
八、开发者选项逐项盘点(学习向清单)
状态列指「用完要不要记得关」;⚠️=影响行为需还原。
| 选项 | 用途 | 注意 |
|---|---|---|
| 充电时保持唤醒 | 长调试不掉屏 | 耗电 |
| USB 调试 / 无线调试 | adb 通道 | 公网/共享环境及时关 |
| 通过 USB 验证应用 | 安装审计 | 一般可开 |
| 指针位置 / 点按显示 | 触摸事件可视化 | 输入类调试常开 |
| 显示屏幕更新 | 重绘高亮 | 找过度绘制 |
| 严格模式 | 主线程 IO 检测 | 崩溃策略自选 |
| 等待调试器 | 进程启动挂起等 JDWP | 配合 AS 断启动 |
| 不保留活动 | 疯狂重建 Activity | 测状态保存神器(a16/02 §六大屏重建回归就靠它) |
| 后台进程限制 | 模拟极限内存 | ⚠️ 用完恢复标准 |
| 动画时长缩放 0.5x/关 | 加速回归 | 录屏对比时别关 |
| 强制 RTL 布局 | 阿拉伯语镜像检查 | ⚠️ |
| 禁用 HW 叠加层 | 全部走 GPU 合成,查 SF 问题 | ⚠️ 影响功耗 |
| GPU 呈现模式分析 | 已退役(见 §四历史说明) | — |
| 启用蓝牙 HCI 记录 | §六 btsnoop | ⚠️ 含敏感数据 |
| 系统跟踪 / 日志生命周期 | logcat 环形缓冲大小 | 调试期调大 |
| 桌面窗口化模式类开关 | 部分大屏设备提供入口 | 以机型实际为准(a16/03 §二) |
| 显示所有 ANR | 忽略“无响应”静默,ANR 全弹 | 压测时制造噪音,日常慎用 |
九、Android 16 新增的观测面(工具侧收编)
- 系统触发的性能分析:注册冷启动/ANR 触发器,系统代采 Perfetto trace 到应用数据目录(ProfilingManager)。线上归因不再靠猜。
- 作业内省:
JobScheduler#getPendingJobReasons(int)/getPendingJobReasonsHistory(int)——「作业为什么不跑」首次可编程回答(a16/01 §二)。 - 启动组件归因:
ApplicationStartInfo.getStartComponent()。 - LNP 演练开关:
am compat enable RESTRICT_LOCAL_NETWORK <pkg>(症状EPERM,a16/02 §十)。 - GPU 加固审计:logcat 扫
avc: denied+/dev/mali0(a16/06 §七)。 - 组件版本:
dumpsys package modules,排障前先对齐 ApexModule 版本。
十、顺手的三条排障剧本(背下来)
- 卡顿:gfxinfo 量化 → Perfetto 主线程 + frame timeline → 锁/Binder/节流定位 → 修后复测同场景。
- ANR/崩溃:dropbox 定位事件 → /data/anr 或 trace 阅读动线(§七)→ events buffer 对齐前因。
- 连接类:logcat events + 子系统 dumpsys(bluetooth/wifi)→ 需要空口真相时 btsnoop → 16 行为变更对照表确认是不是「预期变了」。
本页小结
本页小结:工具链的层级是固定的——logcat/events 给时间线,dumpsys 给系统快照,bugreport 给全集,Perfetto 给「为什么」,btsnoop 给空口真相。dumpsys 按 §二的表当字典用;帧分析告别已退役的 GPU 呈现曲线,走 gfxinfo + Perfetto frame timeline;ANR 按 §七的七步动线读,不再从最后一行栈乱猜。16 给的新观测面(系统触发剖析、作业原因、组件版本)都是「把经验活变成 API」的方向,能用 API 就别再用玄学。
参考资料
- adb 官方文档:https://developer.android.google.cn/tools/adb
- Perfetto 项目与文档:https://perfetto.dev
- Perfetto UI(在线打开 trace / 录制):https://ui.perfetto.dev
- AOSP 图形栈文档:https://source.android.google.cn/docs/core/graphics
- AOSP 平台架构总览(dropbox/ANR 所在的服务侧):https://source.android.google.cn/docs/core/architecture
- ProfilingManager 参考(16 系统触发剖析):https://developer.android.google.cn/reference/android/os/ProfilingManager
- JobScheduler 参考(16 作业内省):https://developer.android.google.cn/reference/android/app/job/JobScheduler
- Wireshark:https://www.wireshark.org
- Android 16 行为变更(本页多处对照):https://developer.android.google.cn/about/versions/16/behavior-changes-all