4. 典型掉帧trace的抓取操作:触发动画、录制trace、结束录制、导出trace文件

4.1 现象识别:什么时候需要手动抓取trace?

在SystemUI动画掉帧排查中,并非所有场景都需要手动抓取trace。出现以下典型现象时,应启动手动trace录制流程:

现象特征判定规则操作优先级
动画明显卡顿、掉帧,肉眼可感知jank > 3帧/100ms高 —— 立即抓取
动画结束时出现闪烁或跳动最后一帧延迟 > 16.6ms高 —— 立即抓取
动画启动延迟超过 200ms从触发到首帧的时间 > 200ms中 —— 安排重现抓取
偶现、难以稳定复现非每次复现,需多次尝试中 —— 开启后台持续录制

4.2 数据采集:四步操作流程

以下操作使用Pixel 6 Pro (Android 14) 和 Perfetto 工具为例。请保证设备已开启“开发者选项”和“USB调试”。

环境准备检查清单:
☑ 设备连接电脑并能通过 adb devices 识别
☑ 已安装最新版 platform-tools (adb 版本 ≥ 33.0.3)
☑ 已安装 perfetto 命令行工具或使用Perfetto UI
☑ SystemUI为debuggable版本(如果是非debug版本,参考章节3的Hack方法)
🔹 步骤1:触发动画 —— 精准触发目标动画

确保在开始录制前已经定位到具体操作入口。例如针对系统下拉通知栏动画:

  • 手动操作:从屏幕顶部向下滑动,触发通知栏展开动画
  • 自动化触发(推荐用于复现场景):
    adb shell am start -a android.intent.action.STATUS_BAR_EXPAND
    sleep 0.5
    adb shell am start -a android.intent.action.STATUS_BAR_COLLAPSE
🔹 步骤2:录制trace —— 使用Perfetto精确控制

推荐使用 Perfetto UI 的 Record 功能或命令行 perfetto 工具。以下是针对SystemUI动画优化的录制配置:

# 命令行录制(持续5秒,覆盖动画触发前后)
adb shell perfetto \
  -c - --txt \
  -o /data/misc/perfetto-traces/trace_$(date +%s).perfetto-trace \
<<'EOF'
buffers: {
    size_kb: 20480
    fill_policy: RING_BUFFER
}
buffers: {
    size_kb: 2048
    fill_policy: DISCARD
}
data_sources: {
    config {
        name: "android.surfaceflinger.frametimeline"
        target_buffer: 0
    }
}
data_sources: {
    config {
        name: "android.graphics.hwui"
        target_buffer: 0
    }
}
data_sources: {
    config {
        name: "android.app.surface"
        target_buffer: 0
    }
}
duration_ms: 5000
EOF
🔹 步骤3:结束录制 —— 等待命令执行完毕或手动停止
  • 自动停止: 设置 duration_ms 后会自行结束。
  • 手动停止: 如果使用 perfetto --background 模式,可通过 adb shell killall perfetto 或 Ctrl+C 停止。
  • 验证文件: 在设备上检查文件是否生成:
    adb shell ls -lh /data/misc/perfetto-traces/
🔹 步骤4:导出trace文件 —— 拉取到本地进行分析
adb pull /data/misc/perfetto-traces/trace_*.perfetto-trace ./trace_dumps/

导出后清除设备端文件(避免占用空间):

adb shell rm /data/misc/perfetto-traces/trace_*.perfetto-trace

4.3 原因定位:trace抓取失败的快速诊断

抓取过程中可能出现的问题及对应的排查树:

Trace 抓取失败诊断故障树 Trace 抓取失败 无数据输出 / 空trace 检查点: ① 缓冲区是否太小?
② 数据源名称是否正确? adb 连接断开 / 权限不足 检查点: ① 是否授权USB调试?
② 是否使用root?
文件导出失败 检查点: ① 目标目录是否存在?
② 是否有写权限?
增大 buffer 至 32MB 使用 adb root 或授权 手动创建目录 常见解决方案总结 1. 使用最新版Perfetto工具 2. 确保SystemUI为debuggable版本 3. 使用 adb shell setprop persist.traced.enable 1 4. 提前预热设备(避免CPU降频影响抓取)

4.4 修复动作:常见错误的纠正方法

针对上一节诊断出的问题,给出具体的修复动作:

问题类型具体现象修复动作
无数据输出trace文件大小为0KB增大 size_kb 至少为 20480,或使用 DISCARD 策略
adb权限拒绝"error: insufficient permissions"执行 adb root(如果设备已root)或检查 ~/Library/Android/sdk/platform-tools 路径
数据源未命中trace中没有SurfaceFlinger数据确保 android.surfaceflinger.frametimeline 名称拼写正确
文件导出失败"Permission denied"先执行 adb shell mkdir -p /data/misc/perfetto-traces/

4.5 复测:验证trace抓取是否成功

执行以下判断规则,确认trace抓取符合预期:

  • 文件大小检查: trace文件大小应至少为 1MB(正常时约 5-20MB)
  • 时间戳覆盖: 使用 Perfetto UI 打开 trace 后,检查时间轴是否覆盖动画触发前后各 1 秒
  • 关键数据源存在: 在 trace 中搜索 “SurfaceFlinger” 和 “hwui” 节点,确认存在且状态为绿色
  • 动画帧可见: 应该能清晰识别出连续的 “VSYNC” 信号和对应的 “doFrame” 调用链
⚠️ 避坑提醒: 如果使用 Perfetto UI 的 Record 向导,请手动调整 Buffer size 为 20480 KB(而非默认的 2048 KB),否则长动画过程可能被截断。

4.6 预防:建立标准化trace抓取SOP

为了降低后续排查成本,推荐团队成员遵循以下标准操作流程(SOP):

  1. 先识别、后抓取: 只有在确认“现象识别”表中匹配项后才启动录制,避免频繁抓取浪费资源。
  2. 使用脚本化连接: 封装一个 capture_trace.sh 脚本,参数化传入动画触发命令和持续时间。
  3. 归档命名规范: 文件命名格式:trace_{日期}T{时间}_{手動/自動}_{动画描述}.perfetto-trace,例如 trace_20241015T1430_manual_notification_expand.perfetto-trace
  4. 环境固化: 在团队开发机中预装 platform-tools 和 perfetto 特定版本,并使用 adb version 校验。
  5. 定期清理设备: 每次抓取后自动执行 adb shell rm -rf /data/misc/perfetto-traces/* 防止磁盘满导致trace异常。