用户点开Camera到看到第一帧画面的时间,直接决定用户体验。冷启动(Cold Start)是性能优化中最复杂的场景——没有缓存、没有预热、从零开始。这篇把MTK Camera冷启动的全链路拆成8个阶段,逐个分析时间瓶颈和优化手段,供大家参考。
一、冷启动 vs 热启动
先搞清楚两个概念:
│ Cold Start │ 冷启动 │
│ (冷启动) │ Camera进程首次创建, 无任何缓存 │
│ │ → Sensor上电, 3A初始化, Pipeline构建 │
│ │ → 耗时最长, 是性能优化的重点 │
│ │ → 典型目标: < 1000ms (从点击到首帧显示) │
├────────────┼──────────────────────────────────────────┤
│ Warm Start │ 热启动 │
│ (热启动) │ Camera进程已存在, 快速重新打开 │
│ │ → Sensor已上电, Pipeline可复用 │
│ │ → 耗时短, 通常 < 300ms │
│ │ → 优化空间有限 │
└────────────┴──────────────────────────────────────────┘
// 用户体验核心指标:
// 点击Camera图标 → 看到第一帧画面的总时间
// 这个时间 = S0 + S1 + S2 + S3 + S4 + S5 + S6 + S7
二、冷启动八阶段总览
MTK Camera冷启动从用户点击图标到首帧显示在屏幕上,共经历8个阶段(S0-S7)。每个阶段都有明确的起止点和时间贡献:
S0 ─── S1 ─── S2 ─── S3 ─── S4 ─── S5 ─── S6 ─── S7
│ │ │ │ │ │ │ │
点击 App Open 配置 创建 提交 首帧 首帧
图标 启动 完成 流流 请求 请求 产生 显示
┌──────┬──────────────────────────────────────────────────┐
│ S0 │ User finger leave camera icon │
│ │ 点击事件 → InputReader → App启动 │
│ │ 时间贡献: ~200ms (系统层, Camera无法控制) │
├──────┼──────────────────────────────────────────────────┤
│ S1 │ App open camera (appstart → connect) │
│ │ APK Activity init → Camera Service连接 │
│ │ 时间贡献: ~400-450ms (APK层) │
├──────┼──────────────────────────────────────────────────┤
│ S2 │ App open done (connect → opendone) │
│ │ Open Device / Init3A / Power on Sensor │
│ │ 时间贡献: ~200-300ms (HAL层, 优化重点) │
├──────┼──────────────────────────────────────────────────┤
│ S3 │ App configure streams (opendone → configure) │
│ │ APK配置Stream → ConfigureStreams │
│ │ 时间贡献: ~400-450ms (APK层) │
├──────┼──────────────────────────────────────────────────┤
│ S4 │ ConfigureStreams done → create request │
│ │ MW ConfigureStreams_3_4 → 创建CaptureRequest │
│ │ 时间贡献: ~50-100ms (MW层) │
├──────┼──────────────────────────────────────────────────┤
│ S5 │ SetRepeating request (configure → submitrequest) │
│ │ App提交request list → Camera Service │
│ │ 时间贡献: ~50-100ms (APK层) │
├──────┼──────────────────────────────────────────────────┤
│ S6 │ First camera frame out (submit → 1st frame) │
│ │ Pipeline执行: P1 → P2A → P2S → Output │
│ │ 时间贡献: ~100-200ms (HAL层, 最核心!) │
├──────┼──────────────────────────────────────────────────┤
│ S7 │ First frame show on panel (1st frame → display) │
│ │ SurfaceFlinger: queueBuffer → VSYNC → 显示 │
│ │ 时间贡献: ~16-50ms (Display层) │
└──────┴──────────────────────────────────────────────────┘
// 总时间: ~1500-2000ms (未优化)
// 优化目标: < 1000ms
// 优化优先级:
// S1/S3 (APK层) → 占比最大, 但Camera团队能力有限
// S2 (HAL层) → Camera团队可直接优化
// S6 (Pipeline) → Camera团队核心战场
// S7 (显示层) → 优化空间有限
三、各阶段深度分析
3.1 S0:点击事件传播
事件链:
Touch事件 → InputReader → InputDispatcher → App
分析:
system_server中查找InputReader
可以获取到点击事件
这个阶段完全在系统层
Camera团队无法优化
典型耗时: ~200ms
3.2 S1:App启动Camera
事件链:
APK Activity init → Camera Service connect
分析:
HIDL层可找到APK发来的cmd
Activity init等操作占用此阶段时间
典型耗时: ~400-450ms
优化方向:
→ APK侧优化: 减少Activity init耗时
→ 预加载: Camera相关Class提前加载
→ 但这通常不在Camera团队的优化范围内
3.3 S2:Open Device与初始化(优化重点)
事件链:
1. Open Device → Camera HAL设备打开
2. Init3A → AE/AWB/AF算法初始化
3. Power on Sensor → Sensor上电
分析:
Power on Sensor通常不直接影响Launch time
因为它在其他线程执行
但仍需关注其完成时间
典型耗时: ~200-300ms
优化方向:
★ 异步初始化: 3A初始化与其他流程并行
★ 延迟加载: 非关键模块延迟初始化
★ Sensor上电优化: 减少上电时序等待
★ 预分配Buffer: Pipeline Buffer提前分配
3.4 S3-S5:配置与提交
APK配置Stream → 典型耗时: ~400-450ms
这部分时间主要在APK侧
S4: ConfigureStreams done → create request
MW ConfigureStreams_3_4 → 创建CaptureRequest
典型耗时: ~50-100ms
S5: SetRepeating request (configure → submitrequest)
App提交request list → Camera Service
典型耗时: ~50-100ms
优化方向:
→ 减少ConfigureStreams的Stream数量
→ 简化Request的Surface配置
→ MW层Pipeline构建优化
四、S6深度分析:首帧Pipeline(核心战场)
S6是从提交Request到首帧产出的时间,是Camera团队最核心的优化战场。它分为4个子阶段:
┌──────────────────────────────────────────────────────────┐
│ S6_1: App Request → Camera HAL process request │
│ │
│ ① App Request → Cameraservice │
│ ② Cameraservice → Camera HAL │
│ ③ Camera HAL process request │
│ │
│ 这三步的总时间是关键, 称为S6_1 │
│ 典型耗时: ~30-50ms │
├──────────────────────────────────────────────────────────┤
│ S6_2: P1 → P2A dispatch │
│ │
│ P1 release → P2 dispatch → P2A Loop In │
│ │
│ Pass1 Ring Buffer释放第一帧 │
│ → 触发Pass2 Dispatch │
│ → P2A(Preview) Loop进入处理 │
│ │
│ 典型耗时: ~20-40ms │
├──────────────────────────────────────────────────────────┤
│ S6_3: P2S process frame │
│ │
│ P2S处理帧 = P2A process + 3rd feature process time │
│ │
│ Pass2 Streaming处理首帧: │
│ → ISP处理 (BPC/CT/DBS/Color/Gamma等) │
│ → 第三方Feature Node处理 │
│ → 图像后处理 │
│ │
│ 典型耗时: ~30-60ms │
├──────────────────────────────────────────────────────────┤
│ S6_4: P2S out → image to app │
│ │
│ P2S输出 → convertImage → 送给App │
│ │
│ convertImage stream 0 = streaming data (Preview) │
│ → 将处理后的图像转换为App可用的格式 │
│ → 通过CameraService回调给App │
│ │
│ 典型耗时: ~10-20ms │
└──────────────────────────────────────────────────────────┘
// S6总典型耗时: ~90-170ms
// 优化目标: < 100ms
S6优化要点
1. P1 Ring Buffer优化
→ 预热Ring Buffer, 避免首次分配
→ 减少Pass1等待Sensor出帧的时间
→ 检查RRZO/IMGO size配置是否合理
2. P2A Pipeline优化
→ 减少不必要的Feature Node
→ 首帧可降级处理 (关闭非关键Feature)
→ 检查P2A Loop是否有不必要的等待
3. P2S处理优化
→ ISP Pipeline串并行优化
→ 第三方Feature Node延迟加载
→ 首帧可跳过部分处理 (如NR/HRD)
4. Output优化
→ convertImage优化, 避免不必要的格式转换
→ 确认Surface配置正确, 无冗余Stream
→ Buffer流转效率优化
五、S7:首帧显示在屏幕
S7是首帧从Camera HAL产出到显示在屏幕上的时间。虽然Camera团队优化空间有限,但理解原理很重要:
SurfaceFlinger处理流程:
① queueBuffer
Camera HAL将处理完的帧放入Buffer Queue
② SurfaceView receive buffer
SurfaceView接收到buffer, 进入高优先级处理
③ SurfaceView deque finished
SurfaceView dequeue完成
等待VSYNC_SF信号
④ 等待VSYNC_SF
VSYNC_sf edge信号在SurfaceView deque之前到达
所以需要等待下一个VSYNC周期
这意味着最多等待16.67ms (60Hz屏幕)
⑤ VSYNC_sf edge signal
SurfaceFlinger开始工作
⑥ SurfaceFlinger work and release buffer
SurfaceFlinger处理buffer并释放
⑦ Wait HW_VSYNC (16ms)
SurfaceFlinger释放buffer后
还需等待一个HW_VSYNC (~16ms)
buffer才会刷新到Display
典型耗时: 16-50ms (取决于VSYNC对齐)
// S7优化方向:
// → 减少VSYNC等待: 提前queueBuffer, 对齐VSYNC
// → 减少SurfaceFlinger处理时间
// → 但这通常在Display/系统团队范围内
六、测量工具与方法
6.1 Systrace / Perfetto
// 可以可视化每个阶段的耗时和线程调度
// 抓取命令:
adb shell atrace --async_start
# 打开Camera App
adb shell atrace --async_stop > camera_cold_start.html
// 关注的Trace类别:
# Camera HAL相关的trace:
- camera (CameraService + HAL)
- hal (HIDL调用)
- gfx (SurfaceFlinger)
- sched (CPU调度)
- freq (CPU频率)
# 在Trace中搜索关键字:
- "openCamera" → S1
- "configureStreams" → S3-S4
- "submitRequestList" → S5
- "processCaptureRequest" → S6
- "queueBuffer" → S7
// Perfetto (新平台替代Systrace):
adb shell perfetto -o /data/misc/perfetto-traces/camera.trace \
-t 10s sched freq idle cam gpu gfx
adb pull /data/misc/perfetto-traces/camera.trace
6.2 MTKLogger
// 用于精确分析每个阶段的耗时
// 开启Camera相关日志:
adb shell setprop debug.camera.log 1
adb shell setprop vendor.debug.camera.log 1
adb shell setprop debug.hal3av3.log 1
adb shell setprop debug.aaa_log.enable 1
// 抓取后搜索关键字:
// S1-S2: "openCamera" / "connect" / "openDevice"
// S3-S4: "configureStreams" / "CreateCaptureRequest"
// S5: "submitRequest" / "setRepeatingRequest"
// S6: "processCaptureRequest" / "P1" / "P2A" / "P2S"
// S7: "queueBuffer" / "onFrameAvailable"
// cold_start.html (如果平台支持):
// 直接打开浏览器查看各阶段耗时分析
6.3 测量方法标准化
1. 重启手机, 等待系统稳定 (至少2分钟)
2. 清理后台进程 (确保Camera进程不存在)
3. 开启Systrace/MTKLogger
4. 点击Camera图标
5. 等待首帧显示
6. 停止抓取
7. 分析各阶段耗时
// 测量注意事项:
// - 每次测量至少3次, 取平均值
// - 测量前关闭省电模式 (避免CPU限频)
// - 注意温度影响 (过热会降频)
// - 区分冷启动和热启动
// - 记录测量时的系统版本和配置
// 快速判断:
// 总时间 > 1500ms → 需要优化
// S2 > 300ms → HAL初始化有问题
// S6 > 150ms → Pipeline有瓶颈
// S7 > 50ms → 显示层有延迟
七、常见瓶颈与优化手段
│ # │ 瓶颈 │ 优化手段 │
├────┼─────────────────────────┼──────────────────────────────┤
│ 1 │ Sensor上电慢 │ 异步上电, 与App init并行 │
│ │ │ 优化I2C通信频率 │
├────┼─────────────────────────┼──────────────────────────────┤
│ 2 │ 3A初始化耗时长 │ 延迟非关键3A模块初始化 │
│ │ │ 预加载默认参数 │
│ │ │ 并行初始化AE/AWB/AF │
├────┼─────────────────────────┼──────────────────────────────┤
│ 3 │ P1 Ring Buffer首次分配 │ 预分配Buffer, 避免首次动态分配 │
│ │ │ 合理设置Buffer Count │
├────┼─────────────────────────┼──────────────────────────────┤
│ 4 │ P2 Pipeline构建慢 │ 简化首帧Pipeline │
│ │ │ 首帧降级: 关闭NR/HRD等Feature │
│ │ │ Feature Node延迟加载 │
├────┼─────────────────────────┼──────────────────────────────┤
│ 5 │ ISP处理首帧慢 │ 检查首帧分辨率是否合理 │
│ │ │ 避免首帧不必要的全分辨率处理 │
│ │ │ ISP Clock频率是否足够 │
├────┼─────────────────────────┼──────────────────────────────┤
│ 6 │ ConfigureStreams重复 │ 减少不必要的Stream配置 │
│ │ │ 合并Preview和VideoStream │
├────┼─────────────────────────┼──────────────────────────────┤
│ 7 │ SurfaceFlinger VSYNC │ 提前queueBuffer对齐VSYNC │
│ │ 等待 │ 减少Buffer转换延迟 │
├────┼─────────────────────────┼──────────────────────────────┤
│ 8 │ CPU频率不足导致 │ Camera场景提升CPU最低频率 │
│ │ Pipeline慢 │ 确保Camera期间不被限频 │
│ │ │ 检查thermal throttling │
└────┴─────────────────────────┴──────────────────────────────┘
八、性能优化速查表
┌───────────┬──────────────┬───────────────────────────────┐
│ 阶段 │ 典型耗时 │ 优化重点 │
├───────────┼──────────────┼───────────────────────────────┤
│ S0 点击 │ ~200ms │ 系统层, 无法优化 │
├───────────┼──────────────┼───────────────────────────────┤
│ S1 启动 │ ~400-450ms │ APK层, 预加载 │
├───────────┼──────────────┼───────────────────────────────┤
│ S2 打开 │ ~200-300ms │ ★ HAL层优化重点 │
│ │ │ 异步初始化, 预分配Buffer │
├───────────┼──────────────┼───────────────────────────────┤
│ S3 配置 │ ~400-450ms │ APK层, 减少Stream数量 │
├───────────┼──────────────┼───────────────────────────────┤
│ S4 创建 │ ~50-100ms │ MW层, Pipeline构建优化 │
├───────────┼──────────────┼───────────────────────────────┤
│ S5 提交 │ ~50-100ms │ APK层 │
├───────────┼──────────────┼───────────────────────────────┤
│ S6 首帧 │ ~90-170ms │ ★★ 核心优化战场 │
│ │ │ P1预热/P2降级/Feature延迟加载 │
├───────────┼──────────────┼───────────────────────────────┤
│ S7 显示 │ ~16-50ms │ VSYNC对齐 │
├───────────┼──────────────┼───────────────────────────────┤
│ 总计 │ ~1500-2000ms │ 优化目标: < 1000ms │
└───────────┴──────────────┴───────────────────────────────┘
工具速查:
Systrace: atrace --async_start/stop
Perfetto: adb shell perfetto -t 10s sched freq cam gpu
MTKLogger: setprop debug.camera.log 1
日志关键字:
S1-S2: openCamera / connect / openDevice
S3-S4: configureStreams / CreateCaptureRequest
S5: submitRequest / setRepeatingRequest
S6: processCaptureRequest / P1 / P2A / P2S
S7: queueBuffer / onFrameAvailable
📌 性能优化核心: 阶段拆解 → 定位瓶颈 → S2异步化 → S6降级 → 测量验证
小结:Camera冷启动性能优化是一个系统工程。S0-S7八个阶段中,Camera团队的核心战场在S2(HAL初始化)和S6(Pipeline执行)。S2优化靠异步化和预分配,S6优化靠Pipeline降级和Feature延迟加载。工具上Systrace/Perfetto看全局,MTKLogger看细节。记住优化三步曲:先测量定位瓶颈,再针对性优化,最后复测验证效果。
更多Camera开发实战内容
欢迎加入知识星球「小驰成长圈」
120+ Camera工程师 · 340+ 实战内容 · 已运营1565天
微信扫码 · 加入星球
评论 (0)