Camera open 慢、Audio underrun、WebView 首屏卡住、Flutter/游戏掉帧,这类问题的证据会散在 App、system_server、cameraserver/audioserver、HAL、SurfaceFlinger 和调度轨道里。只在 UI 里多看几条轨道,很容易漏掉关键时间点。
第 17 篇用 Camera 和 Audio 举例,讲一套可复用的专项分析方法:先抓对数据,再识别对象,再算阶段和阻塞,报告里保留能跳回 UI 复查的时间点。Camera/Audio 是例子,核心是领域 schema 和平台 tracing 协作。读完之后,至少能把 Camera open 慢拆成可复查阶段,把 Audio underrun 拆成周期异常,而不是只交一个 Top slice 表。
这篇默认沿用前文的 UI、SQL、质量检查和现场 Trace 方法。专项分析沿用这些工具,只是按领域对象重新组织。
领域分析从对象字典开始
Camera 和 Audio 的难点不在“有没有 camera/audio 这个 category”,而在 Trace 里到底有哪些对象:
| 领域 | 对象 | 为什么要识别 |
|---|---|---|
| Camera | App client、cameraserver、provider、HAL、request/session id |
open、configure、preview、capture 可能分散在不同进程 |
| Audio | App audio thread、audioserver、MixerThread、FastMixer、audio HAL、Bluetooth/audio route |
underrun 往往来自周期抖动、写入不稳、HAL 阻塞或调度延迟 |
自动化分析的第一步是生成对象字典:相关进程、线程、track、slice 名称、log tag、request/session id。后面的 SQL 不直接猜根因,只围绕这个字典计算阶段耗时和阻塞证据。
对象字典建议由脚本输出,不要只存在于人脑里的一组关键词。一次 Camera case 里可能同时出现 App 进程、cameraserver、provider@2.7-service、vendor camera daemon、codec、SurfaceFlinger;一次 Audio case 里可能同时出现 App、audioserver、audio.primary、Bluetooth、media codec。
确认后的对象字典先长这样,SQL 只是生成和验证它的一种方式:
1 | object_dictionary_version: camera_audio_v1 |
领域 schema 是 App、平台、SQL 和报告之间的协作接口。它要版本化,而不是散在文章、脚本和口头约定里:
1 | schema_version: camera_domain_v1 |
脚本先把候选对象列出来,领域负责人再确认哪些对象属于本次场景。确认结果不能只停在人脑里,要写成 domain_objects 表或同结构的 YAML/JSON,后续查询只 JOIN 这张字典。
1 | CREATE PERFETTO TABLE domain_objects AS |
这张表的字段至少要覆盖 role、进程/线程、track_id、厂商别名、置信度和人工确认状态。第一版仍然可以靠关键词生成,但报告只能使用 owner_confirmed = 1 的对象。否则 vendor HAL、provider、codec、Bluetooth route 一漂移,自动化还是会退回模糊匹配。
候选对象可以这样列给领域负责人复查:
1 | SELECT DISTINCT |
这一步的输出要人工看一眼。自动化可以缩小范围,但不能凭 LIKE 把 provider、HAL、codec、Bluetooth route 的归属全判准。
确认后的对象要写回同一张表,或者落成一份同结构的 YAML/JSON。这个最小示例把本次 Camera open 相关对象标记成报告可用对象,并给它们补上角色。
1 | UPDATE domain_objects |
后续 SQL 只使用 owner_confirmed = 1 的对象。候选表负责找全,确认表负责让报告稳定。固定 role enum 包括:camera_app_client、camera_service、camera_provider、camera_hal、display_service、audio_app、audio_server、audio_mixer、audio_hal、bluetooth_audio。
配置从领域 preset 开始
权限边界要先写清:
| 能力 | 谁能做 | 说明 |
|---|---|---|
| App marker / metadata | 普通 App | android.os.Trace、NDK ATrace、Track Event、业务元数据 |
| 已登记 trigger | 普通 App 或测试 harness | 只能激活平台预先声明的 trigger 名称 |
| App profiling | shell + profileable 或 debuggable |
release 性能对比优先 profileable,debuggable 只用于调试 |
| ftrace/process stats/FrameTimeline/system log | shell、Traceur、平台/OEM 受信 consumer | 受 SELinux 和 build 类型限制,普通 App 不能开启 |
| 上传、限频、隐私、preset 选择 | 平台/OEM 诊断流程 | 必须有授权、脱敏、保留周期和审计 |
下面这份是 lab_domain_debug 配置,不是低开销 field preset。它保留 sched/freq/idle、Camera/Audio/hal/binder atrace、FrameTimeline、process stats 和 log,用于研发设备、userdebug 或实验室复现。field 版本应减到必要数据源,log、binder_lock、高频领域事件只在专项短 trace 打开。
Android 9/10 非 Pixel 可能需要先启用 traced;Android 12 前非 root 不要假设 perfetto 能直接读 /data/local/tmp 配置,优先用 stdin。Camera 如果要量“用户可见首帧”,还需要 SurfaceFlinger/FrameTimeline;只看 camera/HAL 只能量到 API 返回、HAL buffer 或 provider 阶段。
1 | duration_ms: 30000 |
atrace_categories 打开的是 Android 系统 category,不会自动打开 App 里的 android.os.Trace 或 NDK ATrace;App 侧 ATrace 共享 ATRACE_TAG_APP,需要按包名配置 atrace_apps,没有独立 category 过滤。需要参数和跨线程关联时,改用第 13 篇的 Perfetto SDK Track Event。
user build 上采 App 侧 profiling 或部分本地调试信号时,release 包应使用 <profileable android:shell="true" />;debuggable 会改变性能特征,只适合调试,不适合严肃耗时对比。系统服务、HAL、CPU/native profiling 另走 userdebug/eng 或平台诊断权限。
android.log 只在 Android userdebug 构建上支持。user build 或线上场景不要假设日志一定在 Trace 里,外部 logcat、bugreport 或平台侧脱敏日志应放进同一个 case 包。现场包只保留白名单 tag 和窗口摘要,原始 log 要走授权和脱敏。
category 名称也要以目标系统为准。Perfetto 文档把 ATrace 分成 system category 和 per-app events,系统 category 来自 Android 内部进程;App event 共享 ATRACE_TAG_APP,需要按包名启用。写 preset 时不要只复制别人机器上的 category 列表,最好在 Perfetto UI 的 Record 页面或设备侧配置里确认当前版本支持什么。
buffers.size_kb 是 Perfetto central buffer,不等于 ftrace per-CPU kernel ring buffer。sched/ftrace 丢失要看 stats 里的 ftrace overrun/dropped/data_loss;必要时才调 ftrace_config.buffer_size_kb、drain_period_ms 这类参数,并先在短 trace 验证设备兼容性和开销。新增 vendor kernel tracepoint 要先确认 /sys/kernel/tracing/events/*/*/format、字段稳定性和 Perfetto parser/stdlib 支持;否则只能作为 raw ftrace 候选证据,或需要改 Perfetto parser / 自定义 data source。
质量门禁不要只写一个抽象分数。至少固定跑这条 SQL:
1 | SELECT name, idx, severity, source, value |
idx 对应 TraceConfig 的 buffer 下标。报告要按 affected_signal 分组:ftrace/sched、atrace/systrace、track_event、FrameTimeline、android.log、clock、central_buffer。RING_BUFFER 下的 overwritten 要单独解释:它可能只是窗口外旧数据被覆盖,也可能说明问题前证据不够长。报告要把 data loss、packet loss、overwrite 分开降级。
Camera 看阶段
Camera open 慢不能只写“camera 慢”。至少拆成这些阶段:
| 阶段 | owner | 关注点 |
|---|---|---|
| App 发起 open | App marker | 用户操作、权限、UI thread 是否等待 |
App 到 cameraserver |
App + camera service | Binder 往返、服务端线程池是否拥塞 |
cameraserver 到 provider/HAL |
platform event | provider 进程、HAL 线程、设备等待 |
| configure streams | platform/HAL event | stream 数量、分辨率、Surface、HAL configure 耗时 |
| first HAL buffer | HAL/provider event | request 提交、buffer 从 HAL 返回 |
| first presented frame | FrameTimeline/SurfaceFlinger + App marker | buffer 进入 SurfaceFlinger 后被用户看到 |
| capture/result | platform/HAL event | request id、result callback、buffer/metadata 返回 |
这里有三个不同口径:API 调用返回、第一帧从 HAL 返回、第一帧被用户看到。前两个偏 Camera framework / HAL,第三个还要经过 BufferQueue、SurfaceFlinger 和 FrameTimeline。报告里要写清你量的是哪一个,不然“open 变快了”可能只是 API 更早返回,预览首帧并没有提前。
专项 SQL 必须绑定问题窗口。这个窗口可以来自 trigger metadata、业务 marker、用户复现步骤,或者人工在 UI 中选出的区间。缺 owner 事件时,报告写 missing_owner_event 或 stage_unavailable,不要把 LIKE 查询升级成阶段结论。
1 | WITH target_window AS ( |
稳定事件存在时,先用事件计算阶段。缺某个事件时,状态列要输出 stage_unavailable,耗时列保持空值,不要补一个看起来已经量化完成的数字:
1 | WITH target_window AS ( |
如果稳定事件还没补齐,再退回候选 slice 查询。这个查询只用于建立候选阶段,重点看 process_name、thread_name、slice_name 和 dur_ms,不能直接替代上面的阶段口径:
1 | WITH target_window AS ( |
如果这条查不到足够的阶段信息,通常有两种处理:补 android.os.Trace / ATRACE / Track Event,或者让平台侧在 CameraService、provider、HAL 关键阶段补稳定事件名。事件参数里要校验 camera_id/session_id/request_id;用 Track Event 时从 args/debug annotation 或 flow id 取,不要只靠事件名。
Audio 看周期
Audio 问题比 Camera 更强调周期性。一次长 slice 不一定导致听感问题,连续几个 mixer 周期抖动、App 写入间隔不稳、HAL 写入阻塞,才更接近 underrun 或断续。
Audio 报告优先看三件事:周期尾部是否变长,连续异常是否出现,异常是否和 underrun log、route change 或听感时间点重合。Top slice 只作为辅助线索。
Audio 候选 slice 也要绑定问题窗口,并优先使用 domain_objects,避免整段 trace 的历史噪声混进来:
1 | WITH target_window AS ( |
再看 audioserver 的 Mixer/FastMixer 运行周期。这里输出 start-to-start 周期和 off-CPU gap:前者只能发现周期异常,不能直接说明被锁、Binder 或 HAL 写入打断;原因还要关联 thread_state、HAL slice、underrun log 和 route metadata。
1 | WITH target_window AS ( |
Audio 自动化报告里,周期异常比单个 Top slice 更有价值。start_to_start_period_ms 说明节奏是否变长,off_cpu_gap_ms 说明两次运行之间空档是否变大;要判断 CPU 等待、HAL write、route/offload 变化或正常 idle,还要再看对应 slice、thread_state 和 log。
不要给 period_ms 写一个跨设备固定阈值。它和 sample rate、buffer size、fast path、Bluetooth route、offload、AAudio/OpenSL ES/AudioTrack 使用方式都有关系。更稳的做法是:同一设备同一 route 下拿一段干净播放作为基线,再比较异常现场里周期尾部是否变长、是否连续变长、是否和 underrun log 或听感时间点重合。
Running 和 Runnable 分开算
很多专项报告会把线程状态混在一起写。建议分开:
- Running:线程已经在 CPU 上执行,用
sched算。 - Runnable:线程想运行但没拿到 CPU,用
thread_state.state IN ('R', 'R+')算。R+表示 runnable/preempted,也应计入调度等待。
运行态分析有前置条件:必须采到 sched_switch、wakeup/waking,且 stats 里没有 ftrace_cpu_has_data_loss、overrun 或 dropped。否则只能写“调度证据不完整”,不能写“没有 CPU 等待”。
这条 SQL 对问题窗口内的领域线程同时输出 Running 和 Runnable:
1 | WITH target_window AS ( |
如果 Runnable 很高,优先看 CPU 竞争、线程优先级、频率和唤醒源;如果 Running 很高,再考虑 CPU profiling 或函数级热点。
Log 用来补阶段语义
日志适合补 request id、session id、route change、underrun、错误码。Trace 里有 android.log 时,也要限制在问题窗口内:
1 | WITH target_window AS ( |
不要把 log 当成唯一证据。它负责给阶段命名,耗时和阻塞仍要回到 slice、sched、thread_state、Binder 和 HAL 线程。
报告输出要能回 UI
自动化报告不要只吐 SQL 表。建议固定四块:
| 模块 | 输出 |
|---|---|
| 数据质量 | Trace 时长、stats 异常、关键数据源是否存在 |
| 对象字典 | 相关进程、线程、track、log tag、request/session id、确认状态 |
| 阶段指标 | Camera open/config/HAL buffer/presented frame,Audio write/mix/output 周期 |
| 复查点 | ts、dur、进程、线程、slice/log 名称 |
示例结构可以这样写:
1 | Camera open analysis |
报告里每个异常都要能跳回 Perfetto UI。只有结论没有时间点,别人没法复查。
对领域负责人来说,报告要指向可复查的时间段,而不是停在“脚本判断 Camera HAL 慢”。例如 provider configure 花了 98ms、对应 request id 是 17、同一时间 Binder 线程 Runnable 41ms、没有 data loss。脚本负责把上下文整理到一起,最终结论仍要能被 UI 和源码路径复核。
服务端和问题包还要有机器可读的 summary.json:
1 | { |
让 App 和平台补稳定事件
Camera/Audio 自动化最怕名称漂移。不同 Android 版本、厂商 HAL、相机模组、音频路由,slice 名称都可能变。可控代码里应补稳定事件:
| 事件 | owner | required args | 用途 | 隐私边界 |
|---|---|---|---|---|
Camera#OpenStart |
App | camera_id, session_id, event_id |
open_api 起点 | 不写用户内容 |
Camera#OpenEnd |
App | camera_id, session_id, event_id, result |
open_api 终点 | 错误码白名单 |
Camera#ConfigureStreamsStart |
platform | camera_id, session_id, stream_id |
configure 阶段起点 | 分辨率/格式可保留 |
Camera#FirstPreviewFrame |
platform/App | camera_id, session_id, stream_id, surface_id |
可见首帧候选 | 不写画面内容 |
Audio#TrackStart |
App/platform | track_id, route, sample_rate, buffer_frames |
音频周期起点 | route 用枚举 |
Audio#WriteBuffer |
App | track_id, frames, buffer_level |
App 写入节奏 | 不写媒体内容 |
Audio#Underrun |
platform | track_id, route, sample_rate, buffer_frames, underrun_count |
underrun 事件 | route/tag 白名单 |
Audio#RouteChange |
platform | old_route, new_route, reason |
route 变化 | 不写设备唯一标识 |
这些事件可以来自 android.os.Trace、NDK ATrace、Perfetto SDK Track Event 或平台侧 ATRACE。事件名要稳定,不能把动态 id 拼进事件名。
如果用 ATrace,重点是稳定 slice 名和 async cookie。ID 类信息优先放 Track Event 参数、flow id、log/side table 或同一 case 的元数据;counter 只放 queue depth、buffer level、underrun count 这类可解释数值。需要更完整的参数和跨线程关联时,优先用第 13 篇讲过的 Perfetto SDK Track Event。
平台自定义 data source 优先级更低。只有高频、强结构化,或普通 slice/counter 表达不了时才做;manifest 里要写清 data source name、producer 进程、SELinux 域、TraceConfig、解析器和 SQL 兼容策略。
从专项方法扩展到问题清单
Camera/Audio 只是例子。团队要把 Perfetto 用稳,需要把常见现象翻译成采集 preset、采集方、构建类型、分析路径和输出证据。
| 问题 | 基础数据源 | 专项加开 | 默认输出 |
|---|---|---|---|
| UI 卡顿 | sched、freq、idle、gfx、view、wm、input、process_stats、FrameTimeline | binder_driver、App ATrace/Track Event | 问题帧、App/HWUI/SurfaceFlinger 阶段、线程状态 |
| 点击响应慢 | input、sched、freq、view、wm、binder_driver、FrameTimeline | App 视觉状态 counter、高速相机对照 | input 到首个可见变化 |
| App 启动 | sched、freq、am、wm、view、binder_driver、FrameTimeline | log、CPU profiling、App ATrace/Track Event | 启动阶段、首帧、Top wait |
| ANR | sched、freq、binder_driver、am、wm、log | lock、IO、CPU profiling | 主线程等待证据 |
| Binder 慢 | sched、binder_driver、binder_lock、process_stats | system_server log、接口事件 |
慢事务 TopN、server 状态 |
| Native 内存 | process_stats | heapprofd、log、业务 trigger | 分配栈和增长趋势 |
| Camera | sched、freq、camera、hal、binder_driver、FrameTimeline、log | CPU profiling、平台事件 | open/config/HAL buffer/可见首帧 |
| Audio | sched、freq、audio、hal、binder_driver、log | CPU profiling、平台事件 | underrun 前后周期抖动 |
| 功耗/温控 | sched、freq、idle、android.power、thermal、log | GPU counters、devfreq、power rails | 资源趋势和异常窗口 |
每个 preset 都要有负责人、版本、用途、默认窗口、采集方、构建边界、数据源、开销等级、隐私等级和质量门禁。没有这些字段,preset 很快会变成一堆没人敢删的配置:
1 | preset_id: ui_jank_v4 |
普通 App 不能自己开启系统级 ftrace、process stats 或 SurfaceFlinger FrameTimeline session。App 侧能做的是写稳定 marker、发已登记 trigger、补本地元数据;负责持有系统 trace session 的通常是平台服务、OEM 诊断组件、Traceur、shell 或实验室脚本。
user build 上只有 Traceur、shell、平台签名且 SELinux 授权的 OEM 组件能持有系统 trace session;任意普通 App 或未授权诊断 App 都不能直接控制系统级 Perfetto consumer socket。线上只允许审核过的 binary TraceConfig 或 preset id,不下发任意 text proto。
user build 上采 App profiling 还要看 profileable/debuggable。线上自动上传原始 trace、logcat 或 bugreport 之前,必须有用户授权、企业或 OEM 诊断协议、脱敏策略、访问控制、保留周期和审计记录。线上/bugreport 路径要在采集端或读取端配置 trace_filter / 字段级脱敏,并把过滤规则版本写进 case metadata。
报告也要给结论分级:
| 等级 | 写法 | 必须字段 |
|---|---|---|
| 确认 | X 在窗口 A 内阻塞了 Y |
required_signals_available=true、data_quality=clean、ui_review_points>=1、source_sql |
| 倾向 | 更像 X 方向 |
主证据成立,missing_evidence 列出缺源码、日志或领域状态 |
| 排除 | 暂不支持 X 结论 |
signal_present=true 且指标没有支持该方向,不能来自数据缺失 |
| 降级 | 本 Trace 不能判断 X |
degrade_reason 写明 data loss、数据源缺失或样本不足 |
这个分级能保护报告质量。工程讨论里很多争议并不来自 Trace 本身,而是来自结论等级写错:只有“倾向”的证据,被写成了“确认”。
平台和 OEM 侧要建设什么
App 侧能补业务语义,但很多问题发生在 App 看不到的地方:system_server Binder 堵塞、AudioFlinger underrun、Camera HAL 阻塞、Power HAL 策略切换、调度器迁核、GPU 执行轨道不足、Bugreport 里证据散落。平台侧要把四件事固定下来:preset、trigger、证据包格式、自动分析入口。
平台侧不要让工程师每次临时写 TraceConfig。TraceConfig 应该像接口一样被版本化管理,放在仓库里评审、测试、发布:
1 | perfetto-presets/ |
一套 Perfetto 体系至少分三层:
| 层级 | 使用场景 | 采集方 | 采集特点 | 典型数据源 |
|---|---|---|---|---|
| field | user build 线上/灰度问题 | 平台/OEM 诊断组件或 Traceur;App 只发 marker/trigger | 低开销、Ring Buffer、短窗口 stop trigger | sched、process stats、少量 App ATrace、必要 counter |
| lab | 实验室复现和版本对比 | shell、测试框架、平台脚本 | 可控设备、可重复脚本、指标稳定 | FrameTimeline、freq、idle、Binder、领域 log 摘要 |
| deep | 专项排查 | userdebug/root、平台工程工具 | 短时间、高开销、人工操作 | heapprofd、linux.perf、GPU counters、更多 HAL 事件 |
不要把 deep preset 放到线上。CPU profiling、native heap profiling、GPU counters 这类能力在实验室和专项排查里很有价值,但在 user build 的长期现场采集里成本太高,隐私和稳定性风险也更高。
deep preset 的边界要单独写:
linux.perf是采样 profiler,不是全量事件;默认只限短窗口、低频率、目标进程/线程 scope,并写清 unwind、kernel frame、root/userdebug/kptr 限制。- vendor tracepoint 先查
/sys/kernel/tracing/events/*/*/format、字段稳定性和ftrace_setup_errors;未知事件只能作为 raw event 或候选证据。 - field 层禁止
linux.perf、heapprofd、GPU counters、syscall/pagefault 高频事件;必要 counter 必须写采样周期、单位、设备支持范围和上传隐私级别。 - 每个 preset 要有实测写入速率和 data loss 基线,不用一个
cost_level代替真实预算。
Ring Buffer 适合保留触发前后的短窗口,不等于可以无限期留住全量上下文;长 Trace 要用第 15 篇那套后台采集、分段保存和明确退出条件。
trigger 中心也要收敛。App 代理、Framework watchdog、AudioFlinger、CameraService、Thermal/Power、实验室工具都只能发送已登记的 trigger 名称。平台侧再按设备、用户、版本、场景、网络和存储状态限频。名称进入平台后不要随意改,否则服务端索引、SQL 模板、历史趋势和告警规则都会断开。
Bugreport 也要和 Perfetto 结合。bugreport_score > 0 会把正在运行的 trace session 标记为 Bugreport 候选;bugreport_score <= 0 不 eligible。Android dumpstate 调用 perfetto --save-for-bugreport 时,会选择最高分候选 trace 保存到 Bugreport 路径。Android S/T 上会保存候选 trace 并提前停止原 session;Android U+ 上会创建只读快照,原 session 可以继续运行。bugreport_filename 是 Android V / Perfetto v42+ 字段。bugreport_score > 0 还会改变 clone/可附加行为,manifest 里要记录支持版本、隐私等级和可访问主体。
系统埋点要先建字典,再补代码:
1 | camera: |
命名要稳定,含义要能被 SQL 聚合。动态信息放参数、counter 或 metadata,不要拼进事件名。URL、联系人、消息内容、搜索词、地理位置明文不能进入 trace event。
服务端至少要做五件事:文件验收、可信度验收、场景摘要、聚合索引、人工入口。人工打开 UI 前,报告里应该已经写清楚 preset、trigger、触发窗口、质量门禁状态、相关进程线程和机器摘要指向哪个负责人。
处理状态建议写成显式状态机:
1 | ingested |
这个状态机的价值在于约束证据来源:每个结论都能回到同一份 preset、同一条 SQL 和同一种证据等级。版本升级后,如果字段改名、事件缺失、数据源不可用,也能在 quality_checked 阶段直接降级,报告不会继续输出看似确定的结论。
常见坑
- 只按
LIKE '%camera%'会漏掉 provider、vendor HAL、codec、media 进程。 - 只开
atrace_categories会漏掉 App 侧android.os.Trace,需要atrace_apps或 Track Event。 - 普通 App 不能自己打开系统 ftrace/process stats,只能配合平台采集方发 marker 或 trigger。
- UI、启动、点击响应类问题不能把 FrameTimeline 当可选项;没有它时只能降级为线程/阶段分析。
android.log只在 userdebug Trace 里可靠,user build 要准备替代来源。- Binder 慢只是现象,服务端可能在等 HAL、锁、IO 或下游硬件。
- Audio 要看周期抖动,不要只看 Top long slice。
- Camera 要拆 open、configure、preview、capture,不要混成一个总耗时。
- Running 和 Runnable 要分开算,前者看
sched,后者看thread_state。 - Agent 或脚本只能组织证据,不能替代 UI 复查和领域负责人判断。
- Camera 首帧要区分 API 返回、HAL buffer 返回和画面显示。
- Audio 周期阈值要按设备、route、buffer 配置建立基线。
- 线上 preset 越开越重,会带来功耗、隐私和稳定性问题。
- 系统埋点没有字典,事件名漂移后 SQL 和历史趋势都会失效。
- Bugreport 和 Trace 分离,研发要在多个附件里手工找同一时间窗口。
小结
Camera、Audio 这类领域问题的处理方式是:固定 preset,建立对象字典,按阶段和周期写 SQL,输出带时间点的报告,再回 UI 复查异常点。
这套做法可以迁移到 WebView、Flutter、游戏和厂商自定义系统服务。差别只在对象字典和指标模板,底层仍然是 Trace 质量、进程线程归属、阶段耗时、调度状态和日志语义。平台侧再把 preset、trigger、Bugreport、系统埋点、服务端摘要和权限护栏补齐,Perfetto 才能从个人工具变成团队能力。
参考文档
- ATrace data source
- Track events
- Android Log data source
- Android Jank detection with FrameTimeline
- Buffers and dataflow
- Trace Processor Stats
- Getting Started with PerfettoSQL
- Trace Processor Python API
- AOSP Camera HAL
- AOSP Audio architecture
- Advanced System Tracing on Android
- TraceConfig reference
- Android
<profileable>manifest element
关于我 && 博客
欢迎关注 Android Performance。