2、相机启动延迟分析:冷启动 vs 热启动、Activity启动流程、CameraService初始化、HAL设备打开流程、Sensor上电时序

相机启动延迟,说白了就是用户按下相机图标到取景画面出现之间的那段时间。这个时间长短直接影响用户的第一印象。我做过不少项目,客户反馈最多的就是「怎么这么慢?」——嗯,今天我们就来拆解这个延迟到底从哪来的。

2.1 冷启动 vs 热启动:差别在哪?

先搞清楚两个概念。冷启动,指的是相机进程完全不存在,需要从头创建。热启动,则是相机进程已经在后台存活,只是界面被回收了。

对比项 冷启动 热启动
进程状态 不存在,需fork 后台存活
典型耗时 800ms - 1500ms 200ms - 500ms
主要瓶颈 进程创建 + 服务初始化 界面重建 + Surface重连
用户感知 明显等待 几乎无感

我在项目中遇到过一种情况:某款手机冷启动要2秒多,但热启动只要300ms。用户投诉说「相机太慢」,其实他们指的是冷启动。所以优化时,冷启动才是硬骨头。

核心观点:冷启动优化是相机性能的「面子工程」。热启动再快,冷启动慢一样被骂。

2.2 Activity启动流程:从点击到onCreate

用户点击相机图标,系统会做什么?我画了一张图,你看完就明白了。

相机Activity启动流程 用户点击图标 AMS启动Activity 进程创建(冷) Application.onCreate Activity.onCreate setContentView SurfaceView创建 Camera.open startPreview

你想想看,从点击到onCreate,中间经历了什么?AMS要查Intent、要判断进程是否存在、要fork进程(冷启动时)、要加载Application类。这些全是耗时的。

优化小技巧:Application.onCreate里不要做耗时操作。我见过有人在里面初始化图片加载库、数据库、网络库……结果相机启动硬生生多了200ms。把这些东西延迟加载,或者放到子线程去。

2.3 CameraService初始化:服务端在忙什么

Camera.open()调用后,客户端会通过Binder跟CameraService通信。CameraService要做什么?

  1. 加载HAL库——通过dlopen加载camera.provider@2.x.so
  2. 枚举摄像头——调用HAL的getCameraIdList
  3. 创建设备会话——openCameraDevice
  4. 配置流——configureStreams

这里有个坑。我记得有一次,某个平台的HAL库加载花了300ms,原因是so库依赖了太多其他库,导致dlopen时递归加载。后来我们把不必要的依赖去掉,加载时间降到了50ms以内。

注意:CameraService初始化是串行的。如果系统同时有多个相机应用在请求,后面的请求会被阻塞。所以,不要频繁open/close相机。

2.4 HAL设备打开流程:从HAL到Kernel

HAL层打开设备,说白了就是调用open()方法,然后底层驱动开始干活。流程大致如下:

// HAL层调用链
camera_device_t->open()
  └─> vendor_module_open()
       └─> sensor_open()
            └─> v4l2_open("/dev/videoX")
                 └─> kernel driver probe()
                      └─> power on sensor
                      └─> i2c通信初始化
                      └─> mclk配置
                      └─> gpio拉高

这个过程中,最耗时的往往是sensor上电和初始化。我见过一个项目,sensor上电要等100ms,因为驱动里加了不必要的延时。后来我们查datasheet,发现其实50ms就够了。

2.5 Sensor上电时序:为什么这么慢?

Sensor上电不是简单地把电供上就行。它有一套严格的时序要求:

步骤 操作 典型耗时 说明
1 拉高AVDD(模拟电压) 1ms 需要稳定到目标电压
2 拉高DVDD(数字电压) 1ms 需在AVDD之后
3 拉高IOVDD(IO电压) 1ms 最后上电
4 提供MCLK(主时钟) 2ms 时钟稳定时间
5 拉高Reset引脚 1ms 释放复位
6 等待Tdelay 10-50ms sensor内部初始化
7 I2C写入初始化序列 5-20ms 配置寄存器

你看,光上电时序就要20-80ms。这还没算后面的I2C配置。我曾经优化过一个项目,把Tdelay从50ms砍到20ms,因为看了datasheet发现那个延时是给老款sensor用的,新款根本不需要那么久。

关键点:Sensor上电时序的优化空间很大。很多驱动工程师习惯「照搬参考代码」,但参考代码往往留了余量。你完全可以去读datasheet,把不必要的延时去掉。

2.6 整体延迟分布:谁才是罪魁祸首?

我整理了一份典型的冷启动延迟分布数据,你看看:

阶段 耗时(ms) 占比 优化难度
Activity启动(进程创建+onCreate) 300-500 30%
CameraService初始化 100-200 15%
HAL设备打开 100-300 20%
Sensor上电+初始化 100-300 20%
Preview启动(Surface+Stream) 100-200 15%

看到没?Activity启动和Sensor初始化占了半壁江山。所以优化时,优先盯着这两块。

我的建议:拿到一个新平台,先做一次完整的启动trace。用Systrace或者Perfetto抓一下,看看每个阶段花了多少时间。别凭感觉优化,数据说话。

嗯,关于相机启动延迟的分析就到这里。核心思路是:先分清楚冷热启动,再逐段拆解Activity、CameraService、HAL、Sensor这几个环节。每个环节都有优化空间,但你要知道瓶颈在哪,才能对症下药。


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