第九板块: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 的系统级监控

相关推荐
Jinkxs5 小时前
Python基础 - 初识内置函数 Python自带的便捷工具
android·java·python
私人珍藏库5 小时前
【Android】VLLO-韩国热门手机剪辑APP
android·app·工具·软件·多功能
Cloud_Shy6186 小时前
解读《Effective Python 3rd Edition》:从练气到老魔(第六章 Item 40 - 43)
android·开发语言·人工智能·笔记·python·学习方法
AFinalStone7 小时前
Android12 U盘插拔链路源码全解析(五):Framework层(下) StorageManagerService
android·frameworks
林九生8 小时前
【实用技巧】MySQL 绿色版一键路径更新脚本详解 —— update_path.bat 深度解析
android·数据库·mysql
故渊at9 小时前
第十三板块:Android 综合架构与未来演进 | 第三十一篇:Android 架构演进与 Fuchsia OS 的挑战
android·架构·宏内核·微内核·fuchsia·ipc 性能博弈
aqi009 小时前
一文速览 HarmonyOS 6.1.1 推出的十个新特性
android·华为·harmonyos·鸿蒙·harmony
matrixmind110 小时前
aiomysql:异步场景下的 MySQL 驱动
android·数据库·mysql·其他
随遇丿而安10 小时前
第8周:弹窗 / 提示组件全功能与弹窗优化
android