第九板块:Android 多媒体体系 | 第二十四篇:Camera Service 与 HAL3 成像流水线

第九板块:Android 多媒体体系 | 第二十四篇:Camera Service 与 HAL3 成像流水线

所属板块:第九板块 --- Android 多媒体体系

前置知识:第二十三篇中的 AudioFlinger 音频架构、Linux 内核驱动(V4L2)、Binder IPC、内存共享机制(Ashmem/ION)、SurfaceFlinger 显示合成

本篇定位 :这是 Android 设备视觉采集的精密仪器 。如果说屏幕是输出,那么相机就是最高带宽的输入 。本篇将彻底拆解 Camera Service 的架构、HAL3 (Camera HAL 3.x) 的请求/响应模型、Capture Request 的流水线化处理、3A 算法(AF/AE/AWB) 的控制闭环、RAW 域与 YUV 域 的图像处理流程。我们将深入 Camera HAL InterfaceKernel V4L2 DriverFramework Service,揭示 Android 如何在 30ms 内完成从光子到比特的转换。全程无相机拍照代码、无参数调优指南,仅保留 Android 相机系统的底层定义与系统级调度规范。


1. 核心结论先行(Thesis Statement)

Android 的相机系统是一个基于流水线的请求-响应系统

  • Camera Service 的本质相机资源的仲裁者与调度器 。它运行在 System Server 中,管理物理相机设备的生命周期,接收应用层的 CaptureRequest,并将其转换为 HAL 层能理解的指令。
  • HAL3 的本质无状态的流水线 。它抛弃了旧的 API 模型,采用请求驱动 的模式。应用发送一个 CaptureRequest(包含参数和输出 Surface),HAL 处理并返回 CaptureResult(包含元数据和图像缓冲区)。
  • 成像的本质光信号 -> 电信号 -> 数字信号 -> 图像处理 。这是一个从 Sensor (RAW) 经过 ISP (Image Signal Processor) 处理,最终输出 YUV/JPEG 的过程。
  • 零拷贝的本质跨进程共享内存 。应用通过 Surface 提供缓冲区(Buffer),Camera Service 将图像数据直接写入这些缓冲区,避免数据拷贝。

2. 相机架构全景图

2.1 从应用预览到 Sensor 曝光

#mermaid-svg-GtTMErfDuk1nVusb{font-family:"trebuchet ms",verdana,arial,sans-serif;font-size:16px;fill:#333;}@keyframes edge-animation-frame{from{stroke-dashoffset:0;}}@keyframes dash{to{stroke-dashoffset:0;}}#mermaid-svg-GtTMErfDuk1nVusb .edge-animation-slow{stroke-dasharray:9,5!important;stroke-dashoffset:900;animation:dash 50s linear infinite;stroke-linecap:round;}#mermaid-svg-GtTMErfDuk1nVusb .edge-animation-fast{stroke-dasharray:9,5!important;stroke-dashoffset:900;animation:dash 20s linear infinite;stroke-linecap:round;}#mermaid-svg-GtTMErfDuk1nVusb .error-icon{fill:#552222;}#mermaid-svg-GtTMErfDuk1nVusb .error-text{fill:#552222;stroke:#552222;}#mermaid-svg-GtTMErfDuk1nVusb .edge-thickness-normal{stroke-width:1px;}#mermaid-svg-GtTMErfDuk1nVusb .edge-thickness-thick{stroke-width:3.5px;}#mermaid-svg-GtTMErfDuk1nVusb .edge-pattern-solid{stroke-dasharray:0;}#mermaid-svg-GtTMErfDuk1nVusb .edge-thickness-invisible{stroke-width:0;fill:none;}#mermaid-svg-GtTMErfDuk1nVusb .edge-pattern-dashed{stroke-dasharray:3;}#mermaid-svg-GtTMErfDuk1nVusb .edge-pattern-dotted{stroke-dasharray:2;}#mermaid-svg-GtTMErfDuk1nVusb .marker{fill:#333333;stroke:#333333;}#mermaid-svg-GtTMErfDuk1nVusb .marker.cross{stroke:#333333;}#mermaid-svg-GtTMErfDuk1nVusb svg{font-family:"trebuchet ms",verdana,arial,sans-serif;font-size:16px;}#mermaid-svg-GtTMErfDuk1nVusb p{margin:0;}#mermaid-svg-GtTMErfDuk1nVusb .label{font-family:"trebuchet ms",verdana,arial,sans-serif;color:#333;}#mermaid-svg-GtTMErfDuk1nVusb .cluster-label text{fill:#333;}#mermaid-svg-GtTMErfDuk1nVusb .cluster-label span{color:#333;}#mermaid-svg-GtTMErfDuk1nVusb .cluster-label span p{background-color:transparent;}#mermaid-svg-GtTMErfDuk1nVusb .label text,#mermaid-svg-GtTMErfDuk1nVusb span{fill:#333;color:#333;}#mermaid-svg-GtTMErfDuk1nVusb .node rect,#mermaid-svg-GtTMErfDuk1nVusb .node circle,#mermaid-svg-GtTMErfDuk1nVusb .node ellipse,#mermaid-svg-GtTMErfDuk1nVusb .node polygon,#mermaid-svg-GtTMErfDuk1nVusb .node path{fill:#ECECFF;stroke:#9370DB;stroke-width:1px;}#mermaid-svg-GtTMErfDuk1nVusb .rough-node .label text,#mermaid-svg-GtTMErfDuk1nVusb .node .label text,#mermaid-svg-GtTMErfDuk1nVusb .image-shape .label,#mermaid-svg-GtTMErfDuk1nVusb .icon-shape .label{text-anchor:middle;}#mermaid-svg-GtTMErfDuk1nVusb .node .katex path{fill:#000;stroke:#000;stroke-width:1px;}#mermaid-svg-GtTMErfDuk1nVusb .rough-node .label,#mermaid-svg-GtTMErfDuk1nVusb .node .label,#mermaid-svg-GtTMErfDuk1nVusb .image-shape .label,#mermaid-svg-GtTMErfDuk1nVusb .icon-shape .label{text-align:center;}#mermaid-svg-GtTMErfDuk1nVusb .node.clickable{cursor:pointer;}#mermaid-svg-GtTMErfDuk1nVusb .root .anchor path{fill:#333333!important;stroke-width:0;stroke:#333333;}#mermaid-svg-GtTMErfDuk1nVusb .arrowheadPath{fill:#333333;}#mermaid-svg-GtTMErfDuk1nVusb .edgePath .path{stroke:#333333;stroke-width:2.0px;}#mermaid-svg-GtTMErfDuk1nVusb .flowchart-link{stroke:#333333;fill:none;}#mermaid-svg-GtTMErfDuk1nVusb .edgeLabel{background-color:rgba(232,232,232, 0.8);text-align:center;}#mermaid-svg-GtTMErfDuk1nVusb .edgeLabel p{background-color:rgba(232,232,232, 0.8);}#mermaid-svg-GtTMErfDuk1nVusb .edgeLabel rect{opacity:0.5;background-color:rgba(232,232,232, 0.8);fill:rgba(232,232,232, 0.8);}#mermaid-svg-GtTMErfDuk1nVusb .labelBkg{background-color:rgba(232, 232, 232, 0.5);}#mermaid-svg-GtTMErfDuk1nVusb .cluster rect{fill:#ffffde;stroke:#aaaa33;stroke-width:1px;}#mermaid-svg-GtTMErfDuk1nVusb .cluster text{fill:#333;}#mermaid-svg-GtTMErfDuk1nVusb .cluster span{color:#333;}#mermaid-svg-GtTMErfDuk1nVusb div.mermaidTooltip{position:absolute;text-align:center;max-width:200px;padding:2px;font-family:"trebuchet ms",verdana,arial,sans-serif;font-size:12px;background:hsl(80, 100%, 96.2745098039%);border:1px solid #aaaa33;border-radius:2px;pointer-events:none;z-index:100;}#mermaid-svg-GtTMErfDuk1nVusb .flowchartTitleText{text-anchor:middle;font-size:18px;fill:#333;}#mermaid-svg-GtTMErfDuk1nVusb rect.text{fill:none;stroke-width:0;}#mermaid-svg-GtTMErfDuk1nVusb .icon-shape,#mermaid-svg-GtTMErfDuk1nVusb .image-shape{background-color:rgba(232,232,232, 0.8);text-align:center;}#mermaid-svg-GtTMErfDuk1nVusb .icon-shape p,#mermaid-svg-GtTMErfDuk1nVusb .image-shape p{background-color:rgba(232,232,232, 0.8);padding:2px;}#mermaid-svg-GtTMErfDuk1nVusb .icon-shape .label rect,#mermaid-svg-GtTMErfDuk1nVusb .image-shape .label rect{opacity:0.5;background-color:rgba(232,232,232, 0.8);fill:rgba(232,232,232, 0.8);}#mermaid-svg-GtTMErfDuk1nVusb .label-icon{display:inline-block;height:1em;overflow:visible;vertical-align:-0.125em;}#mermaid-svg-GtTMErfDuk1nVusb .node .label-icon path{fill:currentColor;stroke:revert;stroke-width:revert;}#mermaid-svg-GtTMErfDuk1nVusb :root{--mermaid-font-family:"trebuchet ms",verdana,arial,sans-serif;} 硬件模组
Linux 内核
硬件抽象层
System Server
应用进程

  1. createCaptureSession()
  2. 配置 Stream
  3. submitCaptureRequest()
  4. processCaptureRequest()
  5. 配置寄存器
  6. 控制硬件
  7. 曝光/对焦
  8. 光子 -> 电子
  9. 图像处理 (Bayer -> YUV)
  10. 填充 Buffer
  11. onCaptureCompleted()
  12. 图像数据
  13. 图像数据
    Camera2 API
    Preview Surface (SurfaceView/TextureView)
    Capture Surface (ImageReader)
    CameraService
    CameraDeviceClient
    Camera HAL 3.x
    ISP (图像信号处理)
    V4L2 Driver
    Sub-devices (Sensor/Lens/Flash)
    CMOS Sensor
    镜头
    闪光灯

2.2 核心组件职责表

组件 层级 职责 学术定义
CameraService Framework 仲裁者 管理相机设备,处理并发访问,分发请求。
CameraDeviceClient Framework 会话管理者 代表一个应用打开的相机设备,管理 Capture Session。
HAL3 (ICameraDevice) HAL 执行者 厂商实现的接口,接收 Request,返回 Result。
RequestProcessor HAL 流水线调度 将 Request 分解为 ISP 可以执行的原子操作。
Metadata 通用 配置与反馈 键值对(Key-Value),用于配置参数(AE_MODE)和返回状态(SENSOR_EXPOSURE_TIME)。

3. HAL3 的请求-响应模型

3.1 CaptureRequest 的构成

应用发送的每一个请求都是一个完整的指令集。

组成部分 学术定义 示例
Target Surfaces 输出目标 Preview Surface, Capture Surface, Analysis Surface。
Parameters (Metadata) 配置参数 CONTROL_AF_MODE = CONTINUOUS_PICTURE, SENSOR_EXPOSURE_TIME = 10ms
Template 预设模板 TEMPLATE_PREVIEW, TEMPLATE_STILL_CAPTURE。

3.2 流水线处理(Pipeline)

HAL3 将图像处理视为一个流水线。
#mermaid-svg-5olo7D0FsbtT4IhP{font-family:"trebuchet ms",verdana,arial,sans-serif;font-size:16px;fill:#333;}@keyframes edge-animation-frame{from{stroke-dashoffset:0;}}@keyframes dash{to{stroke-dashoffset:0;}}#mermaid-svg-5olo7D0FsbtT4IhP .edge-animation-slow{stroke-dasharray:9,5!important;stroke-dashoffset:900;animation:dash 50s linear infinite;stroke-linecap:round;}#mermaid-svg-5olo7D0FsbtT4IhP .edge-animation-fast{stroke-dasharray:9,5!important;stroke-dashoffset:900;animation:dash 20s linear infinite;stroke-linecap:round;}#mermaid-svg-5olo7D0FsbtT4IhP .error-icon{fill:#552222;}#mermaid-svg-5olo7D0FsbtT4IhP .error-text{fill:#552222;stroke:#552222;}#mermaid-svg-5olo7D0FsbtT4IhP .edge-thickness-normal{stroke-width:1px;}#mermaid-svg-5olo7D0FsbtT4IhP .edge-thickness-thick{stroke-width:3.5px;}#mermaid-svg-5olo7D0FsbtT4IhP .edge-pattern-solid{stroke-dasharray:0;}#mermaid-svg-5olo7D0FsbtT4IhP .edge-thickness-invisible{stroke-width:0;fill:none;}#mermaid-svg-5olo7D0FsbtT4IhP .edge-pattern-dashed{stroke-dasharray:3;}#mermaid-svg-5olo7D0FsbtT4IhP .edge-pattern-dotted{stroke-dasharray:2;}#mermaid-svg-5olo7D0FsbtT4IhP .marker{fill:#333333;stroke:#333333;}#mermaid-svg-5olo7D0FsbtT4IhP .marker.cross{stroke:#333333;}#mermaid-svg-5olo7D0FsbtT4IhP svg{font-family:"trebuchet ms",verdana,arial,sans-serif;font-size:16px;}#mermaid-svg-5olo7D0FsbtT4IhP p{margin:0;}#mermaid-svg-5olo7D0FsbtT4IhP .label{font-family:"trebuchet ms",verdana,arial,sans-serif;color:#333;}#mermaid-svg-5olo7D0FsbtT4IhP .cluster-label text{fill:#333;}#mermaid-svg-5olo7D0FsbtT4IhP .cluster-label span{color:#333;}#mermaid-svg-5olo7D0FsbtT4IhP .cluster-label span p{background-color:transparent;}#mermaid-svg-5olo7D0FsbtT4IhP .label text,#mermaid-svg-5olo7D0FsbtT4IhP span{fill:#333;color:#333;}#mermaid-svg-5olo7D0FsbtT4IhP .node rect,#mermaid-svg-5olo7D0FsbtT4IhP .node circle,#mermaid-svg-5olo7D0FsbtT4IhP .node ellipse,#mermaid-svg-5olo7D0FsbtT4IhP .node polygon,#mermaid-svg-5olo7D0FsbtT4IhP .node path{fill:#ECECFF;stroke:#9370DB;stroke-width:1px;}#mermaid-svg-5olo7D0FsbtT4IhP .rough-node .label text,#mermaid-svg-5olo7D0FsbtT4IhP .node .label text,#mermaid-svg-5olo7D0FsbtT4IhP .image-shape .label,#mermaid-svg-5olo7D0FsbtT4IhP .icon-shape .label{text-anchor:middle;}#mermaid-svg-5olo7D0FsbtT4IhP .node .katex path{fill:#000;stroke:#000;stroke-width:1px;}#mermaid-svg-5olo7D0FsbtT4IhP .rough-node .label,#mermaid-svg-5olo7D0FsbtT4IhP .node .label,#mermaid-svg-5olo7D0FsbtT4IhP .image-shape .label,#mermaid-svg-5olo7D0FsbtT4IhP .icon-shape .label{text-align:center;}#mermaid-svg-5olo7D0FsbtT4IhP .node.clickable{cursor:pointer;}#mermaid-svg-5olo7D0FsbtT4IhP .root .anchor path{fill:#333333!important;stroke-width:0;stroke:#333333;}#mermaid-svg-5olo7D0FsbtT4IhP .arrowheadPath{fill:#333333;}#mermaid-svg-5olo7D0FsbtT4IhP .edgePath .path{stroke:#333333;stroke-width:2.0px;}#mermaid-svg-5olo7D0FsbtT4IhP .flowchart-link{stroke:#333333;fill:none;}#mermaid-svg-5olo7D0FsbtT4IhP .edgeLabel{background-color:rgba(232,232,232, 0.8);text-align:center;}#mermaid-svg-5olo7D0FsbtT4IhP .edgeLabel p{background-color:rgba(232,232,232, 0.8);}#mermaid-svg-5olo7D0FsbtT4IhP .edgeLabel rect{opacity:0.5;background-color:rgba(232,232,232, 0.8);fill:rgba(232,232,232, 0.8);}#mermaid-svg-5olo7D0FsbtT4IhP .labelBkg{background-color:rgba(232, 232, 232, 0.5);}#mermaid-svg-5olo7D0FsbtT4IhP .cluster rect{fill:#ffffde;stroke:#aaaa33;stroke-width:1px;}#mermaid-svg-5olo7D0FsbtT4IhP .cluster text{fill:#333;}#mermaid-svg-5olo7D0FsbtT4IhP .cluster span{color:#333;}#mermaid-svg-5olo7D0FsbtT4IhP div.mermaidTooltip{position:absolute;text-align:center;max-width:200px;padding:2px;font-family:"trebuchet ms",verdana,arial,sans-serif;font-size:12px;background:hsl(80, 100%, 96.2745098039%);border:1px solid #aaaa33;border-radius:2px;pointer-events:none;z-index:100;}#mermaid-svg-5olo7D0FsbtT4IhP .flowchartTitleText{text-anchor:middle;font-size:18px;fill:#333;}#mermaid-svg-5olo7D0FsbtT4IhP rect.text{fill:none;stroke-width:0;}#mermaid-svg-5olo7D0FsbtT4IhP .icon-shape,#mermaid-svg-5olo7D0FsbtT4IhP .image-shape{background-color:rgba(232,232,232, 0.8);text-align:center;}#mermaid-svg-5olo7D0FsbtT4IhP .icon-shape p,#mermaid-svg-5olo7D0FsbtT4IhP .image-shape p{background-color:rgba(232,232,232, 0.8);padding:2px;}#mermaid-svg-5olo7D0FsbtT4IhP .icon-shape .label rect,#mermaid-svg-5olo7D0FsbtT4IhP .image-shape .label rect{opacity:0.5;background-color:rgba(232,232,232, 0.8);fill:rgba(232,232,232, 0.8);}#mermaid-svg-5olo7D0FsbtT4IhP .label-icon{display:inline-block;height:1em;overflow:visible;vertical-align:-0.125em;}#mermaid-svg-5olo7D0FsbtT4IhP .node .label-icon path{fill:currentColor;stroke:revert;stroke-width:revert;}#mermaid-svg-5olo7D0FsbtT4IhP :root{--mermaid-font-family:"trebuchet ms",verdana,arial,sans-serif;} 成像流水线
Sensor 输出 (RAW Bayer)
黑电平校正 (BLC)
镜头阴影校正 (LSC)
去马赛克 (Demosaic)
噪声抑制 (NR)
边缘增强 (Sharpening)
色彩校正 (CCM)
伽马校正 (Gamma)
输出 (YUV/JPEG)

学术定义

  • Bayer Pattern: 传感器输出的原始格式(RGGB, BGGR 等)。
  • Demosaic: 将单通道的 Bayer 数据插值成三通道的 RGB 数据。
  • 3A Algorithms: 自动对焦(AF)、自动曝光(AE)、自动白平衡(AWB)算法在流水线中实时调整参数。

3.3 请求与结果的异步性

HAL3 是完全异步的。

时序

  1. App 发送 Request 1。
  2. App 发送 Request 2。
  3. HAL 处理 Request 1,返回 Result 1。
  4. HAL 处理 Request 2,返回 Result 2。

关键 :Result 的顺序不一定与 Request 的顺序一致(虽然通常一致),系统通过 frameNumber 来关联。


4. Camera Service 的调度机制

4.1 设备状态管理

CameraService 维护着物理相机的状态机。
#mermaid-svg-eVkMlnLlucAA5tkh{font-family:"trebuchet ms",verdana,arial,sans-serif;font-size:16px;fill:#333;}@keyframes edge-animation-frame{from{stroke-dashoffset:0;}}@keyframes dash{to{stroke-dashoffset:0;}}#mermaid-svg-eVkMlnLlucAA5tkh .edge-animation-slow{stroke-dasharray:9,5!important;stroke-dashoffset:900;animation:dash 50s linear infinite;stroke-linecap:round;}#mermaid-svg-eVkMlnLlucAA5tkh .edge-animation-fast{stroke-dasharray:9,5!important;stroke-dashoffset:900;animation:dash 20s linear infinite;stroke-linecap:round;}#mermaid-svg-eVkMlnLlucAA5tkh .error-icon{fill:#552222;}#mermaid-svg-eVkMlnLlucAA5tkh .error-text{fill:#552222;stroke:#552222;}#mermaid-svg-eVkMlnLlucAA5tkh .edge-thickness-normal{stroke-width:1px;}#mermaid-svg-eVkMlnLlucAA5tkh .edge-thickness-thick{stroke-width:3.5px;}#mermaid-svg-eVkMlnLlucAA5tkh .edge-pattern-solid{stroke-dasharray:0;}#mermaid-svg-eVkMlnLlucAA5tkh .edge-thickness-invisible{stroke-width:0;fill:none;}#mermaid-svg-eVkMlnLlucAA5tkh .edge-pattern-dashed{stroke-dasharray:3;}#mermaid-svg-eVkMlnLlucAA5tkh .edge-pattern-dotted{stroke-dasharray:2;}#mermaid-svg-eVkMlnLlucAA5tkh .marker{fill:#333333;stroke:#333333;}#mermaid-svg-eVkMlnLlucAA5tkh .marker.cross{stroke:#333333;}#mermaid-svg-eVkMlnLlucAA5tkh svg{font-family:"trebuchet ms",verdana,arial,sans-serif;font-size:16px;}#mermaid-svg-eVkMlnLlucAA5tkh p{margin:0;}#mermaid-svg-eVkMlnLlucAA5tkh defs #statediagram-barbEnd{fill:#333333;stroke:#333333;}#mermaid-svg-eVkMlnLlucAA5tkh g.stateGroup text{fill:#9370DB;stroke:none;font-size:10px;}#mermaid-svg-eVkMlnLlucAA5tkh g.stateGroup text{fill:#333;stroke:none;font-size:10px;}#mermaid-svg-eVkMlnLlucAA5tkh g.stateGroup .state-title{font-weight:bolder;fill:#131300;}#mermaid-svg-eVkMlnLlucAA5tkh g.stateGroup rect{fill:#ECECFF;stroke:#9370DB;}#mermaid-svg-eVkMlnLlucAA5tkh g.stateGroup line{stroke:#333333;stroke-width:1;}#mermaid-svg-eVkMlnLlucAA5tkh .transition{stroke:#333333;stroke-width:1;fill:none;}#mermaid-svg-eVkMlnLlucAA5tkh .stateGroup .composit{fill:white;border-bottom:1px;}#mermaid-svg-eVkMlnLlucAA5tkh .stateGroup .alt-composit{fill:#e0e0e0;border-bottom:1px;}#mermaid-svg-eVkMlnLlucAA5tkh .state-note{stroke:#aaaa33;fill:#fff5ad;}#mermaid-svg-eVkMlnLlucAA5tkh .state-note text{fill:black;stroke:none;font-size:10px;}#mermaid-svg-eVkMlnLlucAA5tkh .stateLabel .box{stroke:none;stroke-width:0;fill:#ECECFF;opacity:0.5;}#mermaid-svg-eVkMlnLlucAA5tkh .edgeLabel .label rect{fill:#ECECFF;opacity:0.5;}#mermaid-svg-eVkMlnLlucAA5tkh .edgeLabel{background-color:rgba(232,232,232, 0.8);text-align:center;}#mermaid-svg-eVkMlnLlucAA5tkh .edgeLabel p{background-color:rgba(232,232,232, 0.8);}#mermaid-svg-eVkMlnLlucAA5tkh .edgeLabel rect{opacity:0.5;background-color:rgba(232,232,232, 0.8);fill:rgba(232,232,232, 0.8);}#mermaid-svg-eVkMlnLlucAA5tkh .edgeLabel .label text{fill:#333;}#mermaid-svg-eVkMlnLlucAA5tkh .label div .edgeLabel{color:#333;}#mermaid-svg-eVkMlnLlucAA5tkh .stateLabel text{fill:#131300;font-size:10px;font-weight:bold;}#mermaid-svg-eVkMlnLlucAA5tkh .node circle.state-start{fill:#333333;stroke:#333333;}#mermaid-svg-eVkMlnLlucAA5tkh .node .fork-join{fill:#333333;stroke:#333333;}#mermaid-svg-eVkMlnLlucAA5tkh .node circle.state-end{fill:#9370DB;stroke:white;stroke-width:1.5;}#mermaid-svg-eVkMlnLlucAA5tkh .end-state-inner{fill:white;stroke-width:1.5;}#mermaid-svg-eVkMlnLlucAA5tkh .node rect{fill:#ECECFF;stroke:#9370DB;stroke-width:1px;}#mermaid-svg-eVkMlnLlucAA5tkh .node polygon{fill:#ECECFF;stroke:#9370DB;stroke-width:1px;}#mermaid-svg-eVkMlnLlucAA5tkh #statediagram-barbEnd{fill:#333333;}#mermaid-svg-eVkMlnLlucAA5tkh .statediagram-cluster rect{fill:#ECECFF;stroke:#9370DB;stroke-width:1px;}#mermaid-svg-eVkMlnLlucAA5tkh .cluster-label,#mermaid-svg-eVkMlnLlucAA5tkh .nodeLabel{color:#131300;}#mermaid-svg-eVkMlnLlucAA5tkh .statediagram-cluster rect.outer{rx:5px;ry:5px;}#mermaid-svg-eVkMlnLlucAA5tkh .statediagram-state .divider{stroke:#9370DB;}#mermaid-svg-eVkMlnLlucAA5tkh .statediagram-state .title-state{rx:5px;ry:5px;}#mermaid-svg-eVkMlnLlucAA5tkh .statediagram-cluster.statediagram-cluster .inner{fill:white;}#mermaid-svg-eVkMlnLlucAA5tkh .statediagram-cluster.statediagram-cluster-alt .inner{fill:#f0f0f0;}#mermaid-svg-eVkMlnLlucAA5tkh .statediagram-cluster .inner{rx:0;ry:0;}#mermaid-svg-eVkMlnLlucAA5tkh .statediagram-state rect.basic{rx:5px;ry:5px;}#mermaid-svg-eVkMlnLlucAA5tkh .statediagram-state rect.divider{stroke-dasharray:10,10;fill:#f0f0f0;}#mermaid-svg-eVkMlnLlucAA5tkh .note-edge{stroke-dasharray:5;}#mermaid-svg-eVkMlnLlucAA5tkh .statediagram-note rect{fill:#fff5ad;stroke:#aaaa33;stroke-width:1px;rx:0;ry:0;}#mermaid-svg-eVkMlnLlucAA5tkh .statediagram-note rect{fill:#fff5ad;stroke:#aaaa33;stroke-width:1px;rx:0;ry:0;}#mermaid-svg-eVkMlnLlucAA5tkh .statediagram-note text{fill:black;}#mermaid-svg-eVkMlnLlucAA5tkh .statediagram-note .nodeLabel{color:black;}#mermaid-svg-eVkMlnLlucAA5tkh .statediagram .edgeLabel{color:red;}#mermaid-svg-eVkMlnLlucAA5tkh #dependencyStart,#mermaid-svg-eVkMlnLlucAA5tkh #dependencyEnd{fill:#333333;stroke:#333333;stroke-width:1;}#mermaid-svg-eVkMlnLlucAA5tkh .statediagramTitleText{text-anchor:middle;font-size:18px;fill:#333;}#mermaid-svg-eVkMlnLlucAA5tkh :root{--mermaid-font-family:"trebuchet ms",verdana,arial,sans-serif;} 设备未打开
openCamera()
configureStreams()
setRepeatingRequest()
stopRepeating()
重新配置
close()
Closed
Opened
Configured
Active
Idle

4.2 并发访问控制

Android 支持多应用同时访问相机吗?不支持

学术定义

  • 独占访问:CameraService 保证同一时间只有一个进程能打开相机设备。
  • 高优先级抢占 :如果后台应用正在使用相机,前台应用请求打开,CameraService 会强制关闭后台应用(发送 onDisconnected 回调)。

5. 图像缓冲区管理(Buffer Management)

5.1 Surface 与 BufferQueue

应用通过 Surface 向 Camera Service 提供缓冲区。

Surface 类型 用途 缓冲区数量
SurfaceView 预览显示 3 个 (Triple Buffering)
ImageReader 拍照/分析 1-5 个 (取决于 Max Images)
MediaCodec 视频录制 2-3 个

5.2 零拷贝流程

  1. App 创建 Surface,背后是一个 BufferQueue
  2. App 调用 createCaptureSession,CameraService 获取 BufferQueue 的句柄。
  3. App 发送 CaptureRequest,指定 Target 为上述 Surface
  4. HAL 处理完图像,直接将数据写入 BufferQueue 中的一个空闲 Buffer。
  5. App 从 Surface 中获取 Buffer,无需拷贝。

6. 3A 算法的控制闭环

6.1 AE(自动曝光)闭环

AE 是一个动态调整的过程。
#mermaid-svg-7kCuZGCQM3P1scth{font-family:"trebuchet ms",verdana,arial,sans-serif;font-size:16px;fill:#333;}@keyframes edge-animation-frame{from{stroke-dashoffset:0;}}@keyframes dash{to{stroke-dashoffset:0;}}#mermaid-svg-7kCuZGCQM3P1scth .edge-animation-slow{stroke-dasharray:9,5!important;stroke-dashoffset:900;animation:dash 50s linear infinite;stroke-linecap:round;}#mermaid-svg-7kCuZGCQM3P1scth .edge-animation-fast{stroke-dasharray:9,5!important;stroke-dashoffset:900;animation:dash 20s linear infinite;stroke-linecap:round;}#mermaid-svg-7kCuZGCQM3P1scth .error-icon{fill:#552222;}#mermaid-svg-7kCuZGCQM3P1scth .error-text{fill:#552222;stroke:#552222;}#mermaid-svg-7kCuZGCQM3P1scth .edge-thickness-normal{stroke-width:1px;}#mermaid-svg-7kCuZGCQM3P1scth .edge-thickness-thick{stroke-width:3.5px;}#mermaid-svg-7kCuZGCQM3P1scth .edge-pattern-solid{stroke-dasharray:0;}#mermaid-svg-7kCuZGCQM3P1scth .edge-thickness-invisible{stroke-width:0;fill:none;}#mermaid-svg-7kCuZGCQM3P1scth .edge-pattern-dashed{stroke-dasharray:3;}#mermaid-svg-7kCuZGCQM3P1scth .edge-pattern-dotted{stroke-dasharray:2;}#mermaid-svg-7kCuZGCQM3P1scth .marker{fill:#333333;stroke:#333333;}#mermaid-svg-7kCuZGCQM3P1scth .marker.cross{stroke:#333333;}#mermaid-svg-7kCuZGCQM3P1scth svg{font-family:"trebuchet ms",verdana,arial,sans-serif;font-size:16px;}#mermaid-svg-7kCuZGCQM3P1scth p{margin:0;}#mermaid-svg-7kCuZGCQM3P1scth .label{font-family:"trebuchet ms",verdana,arial,sans-serif;color:#333;}#mermaid-svg-7kCuZGCQM3P1scth .cluster-label text{fill:#333;}#mermaid-svg-7kCuZGCQM3P1scth .cluster-label span{color:#333;}#mermaid-svg-7kCuZGCQM3P1scth .cluster-label span p{background-color:transparent;}#mermaid-svg-7kCuZGCQM3P1scth .label text,#mermaid-svg-7kCuZGCQM3P1scth span{fill:#333;color:#333;}#mermaid-svg-7kCuZGCQM3P1scth .node rect,#mermaid-svg-7kCuZGCQM3P1scth .node circle,#mermaid-svg-7kCuZGCQM3P1scth .node ellipse,#mermaid-svg-7kCuZGCQM3P1scth .node polygon,#mermaid-svg-7kCuZGCQM3P1scth .node path{fill:#ECECFF;stroke:#9370DB;stroke-width:1px;}#mermaid-svg-7kCuZGCQM3P1scth .rough-node .label text,#mermaid-svg-7kCuZGCQM3P1scth .node .label text,#mermaid-svg-7kCuZGCQM3P1scth .image-shape .label,#mermaid-svg-7kCuZGCQM3P1scth .icon-shape .label{text-anchor:middle;}#mermaid-svg-7kCuZGCQM3P1scth .node .katex path{fill:#000;stroke:#000;stroke-width:1px;}#mermaid-svg-7kCuZGCQM3P1scth .rough-node .label,#mermaid-svg-7kCuZGCQM3P1scth .node .label,#mermaid-svg-7kCuZGCQM3P1scth .image-shape .label,#mermaid-svg-7kCuZGCQM3P1scth .icon-shape .label{text-align:center;}#mermaid-svg-7kCuZGCQM3P1scth .node.clickable{cursor:pointer;}#mermaid-svg-7kCuZGCQM3P1scth .root .anchor path{fill:#333333!important;stroke-width:0;stroke:#333333;}#mermaid-svg-7kCuZGCQM3P1scth .arrowheadPath{fill:#333333;}#mermaid-svg-7kCuZGCQM3P1scth .edgePath .path{stroke:#333333;stroke-width:2.0px;}#mermaid-svg-7kCuZGCQM3P1scth .flowchart-link{stroke:#333333;fill:none;}#mermaid-svg-7kCuZGCQM3P1scth .edgeLabel{background-color:rgba(232,232,232, 0.8);text-align:center;}#mermaid-svg-7kCuZGCQM3P1scth .edgeLabel p{background-color:rgba(232,232,232, 0.8);}#mermaid-svg-7kCuZGCQM3P1scth .edgeLabel rect{opacity:0.5;background-color:rgba(232,232,232, 0.8);fill:rgba(232,232,232, 0.8);}#mermaid-svg-7kCuZGCQM3P1scth .labelBkg{background-color:rgba(232, 232, 232, 0.5);}#mermaid-svg-7kCuZGCQM3P1scth .cluster rect{fill:#ffffde;stroke:#aaaa33;stroke-width:1px;}#mermaid-svg-7kCuZGCQM3P1scth .cluster text{fill:#333;}#mermaid-svg-7kCuZGCQM3P1scth .cluster span{color:#333;}#mermaid-svg-7kCuZGCQM3P1scth div.mermaidTooltip{position:absolute;text-align:center;max-width:200px;padding:2px;font-family:"trebuchet ms",verdana,arial,sans-serif;font-size:12px;background:hsl(80, 100%, 96.2745098039%);border:1px solid #aaaa33;border-radius:2px;pointer-events:none;z-index:100;}#mermaid-svg-7kCuZGCQM3P1scth .flowchartTitleText{text-anchor:middle;font-size:18px;fill:#333;}#mermaid-svg-7kCuZGCQM3P1scth rect.text{fill:none;stroke-width:0;}#mermaid-svg-7kCuZGCQM3P1scth .icon-shape,#mermaid-svg-7kCuZGCQM3P1scth .image-shape{background-color:rgba(232,232,232, 0.8);text-align:center;}#mermaid-svg-7kCuZGCQM3P1scth .icon-shape p,#mermaid-svg-7kCuZGCQM3P1scth .image-shape p{background-color:rgba(232,232,232, 0.8);padding:2px;}#mermaid-svg-7kCuZGCQM3P1scth .icon-shape .label rect,#mermaid-svg-7kCuZGCQM3P1scth .image-shape .label rect{opacity:0.5;background-color:rgba(232,232,232, 0.8);fill:rgba(232,232,232, 0.8);}#mermaid-svg-7kCuZGCQM3P1scth .label-icon{display:inline-block;height:1em;overflow:visible;vertical-align:-0.125em;}#mermaid-svg-7kCuZGCQM3P1scth .node .label-icon path{fill:currentColor;stroke:revert;stroke-width:revert;}#mermaid-svg-7kCuZGCQM3P1scth :root{--mermaid-font-family:"trebuchet ms",verdana,arial,sans-serif;} 调整
Request: 设定曝光参数
Sensor 曝光
ISP 处理
输出图像
统计亮度值
计算误差

学术定义

  • Exposure Value (EV): 由光圈、快门、ISO 共同决定。
  • Metering Region: 测光区域(如中心权重、平均测光)。

6.2 AF(自动对焦)状态机

#mermaid-svg-rTSEi3XKAd1b2O4n{font-family:"trebuchet ms",verdana,arial,sans-serif;font-size:16px;fill:#333;}@keyframes edge-animation-frame{from{stroke-dashoffset:0;}}@keyframes dash{to{stroke-dashoffset:0;}}#mermaid-svg-rTSEi3XKAd1b2O4n .edge-animation-slow{stroke-dasharray:9,5!important;stroke-dashoffset:900;animation:dash 50s linear infinite;stroke-linecap:round;}#mermaid-svg-rTSEi3XKAd1b2O4n .edge-animation-fast{stroke-dasharray:9,5!important;stroke-dashoffset:900;animation:dash 20s linear infinite;stroke-linecap:round;}#mermaid-svg-rTSEi3XKAd1b2O4n .error-icon{fill:#552222;}#mermaid-svg-rTSEi3XKAd1b2O4n .error-text{fill:#552222;stroke:#552222;}#mermaid-svg-rTSEi3XKAd1b2O4n .edge-thickness-normal{stroke-width:1px;}#mermaid-svg-rTSEi3XKAd1b2O4n .edge-thickness-thick{stroke-width:3.5px;}#mermaid-svg-rTSEi3XKAd1b2O4n .edge-pattern-solid{stroke-dasharray:0;}#mermaid-svg-rTSEi3XKAd1b2O4n .edge-thickness-invisible{stroke-width:0;fill:none;}#mermaid-svg-rTSEi3XKAd1b2O4n .edge-pattern-dashed{stroke-dasharray:3;}#mermaid-svg-rTSEi3XKAd1b2O4n .edge-pattern-dotted{stroke-dasharray:2;}#mermaid-svg-rTSEi3XKAd1b2O4n .marker{fill:#333333;stroke:#333333;}#mermaid-svg-rTSEi3XKAd1b2O4n .marker.cross{stroke:#333333;}#mermaid-svg-rTSEi3XKAd1b2O4n svg{font-family:"trebuchet ms",verdana,arial,sans-serif;font-size:16px;}#mermaid-svg-rTSEi3XKAd1b2O4n p{margin:0;}#mermaid-svg-rTSEi3XKAd1b2O4n defs #statediagram-barbEnd{fill:#333333;stroke:#333333;}#mermaid-svg-rTSEi3XKAd1b2O4n g.stateGroup text{fill:#9370DB;stroke:none;font-size:10px;}#mermaid-svg-rTSEi3XKAd1b2O4n g.stateGroup text{fill:#333;stroke:none;font-size:10px;}#mermaid-svg-rTSEi3XKAd1b2O4n g.stateGroup .state-title{font-weight:bolder;fill:#131300;}#mermaid-svg-rTSEi3XKAd1b2O4n g.stateGroup rect{fill:#ECECFF;stroke:#9370DB;}#mermaid-svg-rTSEi3XKAd1b2O4n g.stateGroup line{stroke:#333333;stroke-width:1;}#mermaid-svg-rTSEi3XKAd1b2O4n .transition{stroke:#333333;stroke-width:1;fill:none;}#mermaid-svg-rTSEi3XKAd1b2O4n .stateGroup .composit{fill:white;border-bottom:1px;}#mermaid-svg-rTSEi3XKAd1b2O4n .stateGroup .alt-composit{fill:#e0e0e0;border-bottom:1px;}#mermaid-svg-rTSEi3XKAd1b2O4n .state-note{stroke:#aaaa33;fill:#fff5ad;}#mermaid-svg-rTSEi3XKAd1b2O4n .state-note text{fill:black;stroke:none;font-size:10px;}#mermaid-svg-rTSEi3XKAd1b2O4n .stateLabel .box{stroke:none;stroke-width:0;fill:#ECECFF;opacity:0.5;}#mermaid-svg-rTSEi3XKAd1b2O4n .edgeLabel .label rect{fill:#ECECFF;opacity:0.5;}#mermaid-svg-rTSEi3XKAd1b2O4n .edgeLabel{background-color:rgba(232,232,232, 0.8);text-align:center;}#mermaid-svg-rTSEi3XKAd1b2O4n .edgeLabel p{background-color:rgba(232,232,232, 0.8);}#mermaid-svg-rTSEi3XKAd1b2O4n .edgeLabel rect{opacity:0.5;background-color:rgba(232,232,232, 0.8);fill:rgba(232,232,232, 0.8);}#mermaid-svg-rTSEi3XKAd1b2O4n .edgeLabel .label text{fill:#333;}#mermaid-svg-rTSEi3XKAd1b2O4n .label div .edgeLabel{color:#333;}#mermaid-svg-rTSEi3XKAd1b2O4n .stateLabel text{fill:#131300;font-size:10px;font-weight:bold;}#mermaid-svg-rTSEi3XKAd1b2O4n .node circle.state-start{fill:#333333;stroke:#333333;}#mermaid-svg-rTSEi3XKAd1b2O4n .node .fork-join{fill:#333333;stroke:#333333;}#mermaid-svg-rTSEi3XKAd1b2O4n .node circle.state-end{fill:#9370DB;stroke:white;stroke-width:1.5;}#mermaid-svg-rTSEi3XKAd1b2O4n .end-state-inner{fill:white;stroke-width:1.5;}#mermaid-svg-rTSEi3XKAd1b2O4n .node rect{fill:#ECECFF;stroke:#9370DB;stroke-width:1px;}#mermaid-svg-rTSEi3XKAd1b2O4n .node polygon{fill:#ECECFF;stroke:#9370DB;stroke-width:1px;}#mermaid-svg-rTSEi3XKAd1b2O4n #statediagram-barbEnd{fill:#333333;}#mermaid-svg-rTSEi3XKAd1b2O4n .statediagram-cluster rect{fill:#ECECFF;stroke:#9370DB;stroke-width:1px;}#mermaid-svg-rTSEi3XKAd1b2O4n .cluster-label,#mermaid-svg-rTSEi3XKAd1b2O4n .nodeLabel{color:#131300;}#mermaid-svg-rTSEi3XKAd1b2O4n .statediagram-cluster rect.outer{rx:5px;ry:5px;}#mermaid-svg-rTSEi3XKAd1b2O4n .statediagram-state .divider{stroke:#9370DB;}#mermaid-svg-rTSEi3XKAd1b2O4n .statediagram-state .title-state{rx:5px;ry:5px;}#mermaid-svg-rTSEi3XKAd1b2O4n .statediagram-cluster.statediagram-cluster .inner{fill:white;}#mermaid-svg-rTSEi3XKAd1b2O4n .statediagram-cluster.statediagram-cluster-alt .inner{fill:#f0f0f0;}#mermaid-svg-rTSEi3XKAd1b2O4n .statediagram-cluster .inner{rx:0;ry:0;}#mermaid-svg-rTSEi3XKAd1b2O4n .statediagram-state rect.basic{rx:5px;ry:5px;}#mermaid-svg-rTSEi3XKAd1b2O4n .statediagram-state rect.divider{stroke-dasharray:10,10;fill:#f0f0f0;}#mermaid-svg-rTSEi3XKAd1b2O4n .note-edge{stroke-dasharray:5;}#mermaid-svg-rTSEi3XKAd1b2O4n .statediagram-note rect{fill:#fff5ad;stroke:#aaaa33;stroke-width:1px;rx:0;ry:0;}#mermaid-svg-rTSEi3XKAd1b2O4n .statediagram-note rect{fill:#fff5ad;stroke:#aaaa33;stroke-width:1px;rx:0;ry:0;}#mermaid-svg-rTSEi3XKAd1b2O4n .statediagram-note text{fill:black;}#mermaid-svg-rTSEi3XKAd1b2O4n .statediagram-note .nodeLabel{color:black;}#mermaid-svg-rTSEi3XKAd1b2O4n .statediagram .edgeLabel{color:red;}#mermaid-svg-rTSEi3XKAd1b2O4n #dependencyStart,#mermaid-svg-rTSEi3XKAd1b2O4n #dependencyEnd{fill:#333333;stroke:#333333;stroke-width:1;}#mermaid-svg-rTSEi3XKAd1b2O4n .statediagramTitleText{text-anchor:middle;font-size:18px;fill:#333;}#mermaid-svg-rTSEi3XKAd1b2O4n :root{--mermaid-font-family:"trebuchet ms",verdana,arial,sans-serif;} 未激活
被动扫描 (预览中)
主动扫描 (点击对焦)
合焦成功
合焦失败
锁定焦点
取消锁定
Inactive
PassiveScan
ActiveScan
Focused
Locked


7. 关键源码深度解析

7.1 CameraService 的请求分发

cpp 复制代码
// frameworks/av/services/camera/libcameraservice/CameraDeviceClient.cpp
status_t CameraDeviceClient::submitRequest(...) {
    // 1. 检查请求合法性
    if (!isRequestValid(request)) {
        return BAD_VALUE;
    }

    // 2. 将 Framework 请求转换为 HAL 请求
    halRequest = convertToHalRequest(request);

    // 3. 调用 HAL 接口
    mHalDevice->processCaptureRequest(halRequest);

    // 4. 更新帧号
    mFrameNumber++;
}

7.2 HAL3 的返回结果

cpp 复制代码
// hardware/interfaces/camera/device/3.2/default/CameraDeviceSession.cpp
void CameraDeviceSession::processCaptureResult(...) {
    // 1. 填充元数据
    result.metadata = mLatestMetadata;

    // 2. 填充图像缓冲区
    result.outputBuffers[0].buffer = mFilledBuffer;

    // 3. 通过回调返回给 Framework
    mCallback->processCaptureResult(result);
}

8. 相机系统的常见误区

误区 学术解释
分辨率越高,画质越好 不一定。高分辨率可能牺牲帧率和进光量,导致噪点增加。
数码变焦是放大像素 是的。数码变焦只是裁剪图像中心区域并插值放大,会损失细节。
夜景模式是全靠算法 不全是。夜景模式需要长曝光(降低 ISO)或多帧合成(提高信噪比)。
前置摄像头比后置差 通常是。物理上,前置摄像头的 Sensor 尺寸、光圈、镜片素质通常低于后置。

9. 本篇总结(Knowledge Closure)

关键点 纯学术定义
Camera Service 的本质 相机资源的仲裁者与调度器,管理设备生命周期。
HAL3 的本质 无状态的请求-响应流水线,基于 Metadata 配置。
成像流水线 从 RAW Bayer 经过 ISP 处理(BLC, Demosaic, NR, CCM)到 YUV。
3A 算法 自动对焦、曝光、白平衡的实时闭环控制系统。
零拷贝机制 通过 Surface/BufferQueue 实现跨进程共享内存,避免数据搬运。

10. 第九板块结语

至此,第九板块:Android 多媒体体系 已全部完结。

我们从 AudioFlinger 的音频合成 出发,深入 AudioPolicyService 的策略仲裁 ,探索 Camera Service 的请求流水线 ,最终抵达 HAL3 的成像处理

我们揭示了 Android 多媒体系统的核心逻辑:用流水线处理高带宽数据,用策略隔离应用,用共享内存消除拷贝。

下一篇预告第十板块:Android 系统稳定性与调试 | 第二十五篇:Watchdog 与 ANR 的系统级监控

相关推荐
千里马学框架1 天前
一起学 Android 14:ShellTransition 屏幕旋转过程深度剖析
android·智能手机·性能优化·framework·性能·屏幕旋转·rotation
美狐美颜SDK开放平台1 天前
开发直播APP时如何接入视频美颜SDK?开发流程与注意事项
android·人工智能·计算机视觉·音视频·直播美颜sdk
AFinalStone1 天前
Android7 SystemUI源码解析(七)Keyguard锁屏模块深度解析
android·systemui
致远ccc1 天前
Google Play 上架前如何测试 App?多国家 Android 环境测试
android·app测试·googleplay·多国家应用测试
ttyyttemo1 天前
Kotlin 协程中的 Job 结构化并发与取消
android
sun0077001 天前
tbox 4g/5g切换,导致wan ip 改变,导致车机旧网络不可用。需要重启车机才行
android
其实防守也摸鱼1 天前
内网穿透与反向代理:原理、工具与实战指南
android·大数据·运维·安全·网络安全·自动化·渗透
AFinalStone1 天前
Android7 SystemUI 源码解析(四)NavigationBar 导航栏与 SystemBars
android·systemui
JMchen1 天前
属性动画原理与高级动画实现
android·kotlin·canvas
AFinalStone1 天前
Android7 SystemUI 源码解析(二)启动流程深度解析
android·systemui