引言:Camera1已死,Camera2当立
你有没有在面试中被问过这样的问题:"为什么Android要废弃Camera1 API?Camera2到底改进了什么?"
如果你的回答只是"因为Camera1太旧了"------那这篇文章正是为你准备的。
Camera1(android.hardware.Camera)在2014年被正式废弃,取而代之的是 Camera2 (android.hardware.camera2)。两者的差别不只是API名字换了几个字母,而是底层设计哲学的彻底重构。Camera1是命令式的------"拍照!""录像!";Camera2是声明式流式的------你描述你想要什么样的数据管道,系统帮你搭好,然后数据自动流淌。
用一个比喻:Camera1像是在餐厅点单(每次拍照都是单独下单),Camera2像是设置一条自动化流水线(配置好了,数据就按你期望的方式持续流出)。
本文是 Android 15 视频子系统系列的第一篇,带你从架构层面彻底理解 Camera2 API 的设计理念和核心概念。
本文内容:
- Camera2 相比 Camera1 的本质改进
- Camera2 五层架构全景解析
- 五大核心组件:CameraManager / CameraDevice / CameraCaptureSession / CaptureRequest / CaptureResult
- CameraCharacteristics 特性查询
- Android 15 相机新特性(Ultra HDR、10-bit视频)
- 调试工具速查
一、Camera1 的问题在哪里?
在深入 Camera2 之前,先理解为何需要改变。
1.1 Camera1 的三大痛点
痛点1:单流输出,无法同时预览+拍照+录像
Camera1 只支持一路输出流(预览到 SurfaceView),想同时录像和高分辨率预览?对不起,做不到。
痛点2:同步阻塞式 API,延迟不可控
java
// Camera1 的拍照 API - 同步阻塞,你无法精确控制时序
camera.takePicture(shutterCallback, rawCallback, jpegCallback);
// 从这一行到 jpegCallback 被调用,中间发生了什么?你不知道。
同步阻塞模型意味着你无法知道快门何时精确触发、曝光何时结束,导致连拍性能差、零快门延迟(ZSL)难以实现。
痛点3:3A 控制粗糙
Camera1 的自动对焦、自动曝光、自动白平衡(3A)无法精细控制,不支持手动 ISO、快门速度等专业参数。这对专业拍照 APP(如相机 APP、手动相机)来说是致命缺陷。
1.2 Camera2 的核心改进
| 维度 | Camera1 | Camera2 |
|---|---|---|
| 输出流数量 | 1路 | 多路并发(预览+拍照+录像同时输出) |
| 控制模型 | 同步命令式 | 异步 Pipeline 流式 |
| 3A 控制 | 粗粒度 | 精细手动控制(ISO/快门/白平衡色温) |
| 时间戳精度 | 不可靠 | 纳秒级时间戳,可精确同步 |
| RAW 格式 | 不支持 | 支持 RAW10/RAW12/RAW16 |
| 多摄像头 | 不支持 | 支持逻辑相机(多摄融合) |
二、Camera2 五层架构全景
Camera2 的技术栈由五层组成,从 Java API 到物理传感器,每层职责清晰:

2.1 应用层(Application Layer)
最顶层,开发者直接打交道的地方:
java
// 典型的 Camera2 开发入口
CameraManager manager = (CameraManager) getSystemService(Context.CAMERA_SERVICE);
String[] cameraIds = manager.getCameraIdList(); // 获取所有相机ID
Camera2 包路径:android.hardware.camera2.*
核心类一览:
CameraManager--- 相机设备管理器(系统服务门口)CameraDevice--- 单个相机设备的抽象CameraCaptureSession--- 相机捕获会话CaptureRequest--- 单次或重复捕获请求CaptureResult--- 捕获结果元数据CameraCharacteristics--- 相机静态特性(只读,出厂就定了)
2.2 Java Framework 层
android.hardware.camera2.* 这些 Java 类并非凭空运行,它们背后是 Java Framework 层:
bash
frameworks/base/core/java/android/hardware/camera2/
关键类:
CameraManager.java--- 通过 Binder 调用CameraService,管理相机设备列表CameraDevice.java--- Binder 代理,真正的实现在 Native 的Camera3DeviceCameraCaptureSession.java--- 会话管理,对应 Native 的CaptureSession
💡 设计模式 :Java 层的这些类本质上都是 Binder 代理 (Proxy),真正的逻辑在 Native 层的
CameraService中执行。Java API 负责 "参数校验 + IPC 调用",性能敏感的代码在 C++ 里跑。
2.3 Native 层(CameraService)
CameraService 是 Android 相机的核心 Native 服务,运行在独立进程 cameraserver 中:
bash
frameworks/av/services/camera/libcameraservice/ # CameraService 实现
frameworks/av/camera/ # Camera Native 客户端库
核心组件:
| 组件 | 职责 |
|---|---|
CameraService |
相机服务入口,多应用仲裁,权限管理 |
Camera3Device |
单个相机设备的完整抽象,管理 Stream 和 Request |
CameraDeviceClient |
Binder 服务端,对接 Java 层的请求 |
CameraProviderManager |
管理所有 Camera HAL Provider |
2.4 HAL 层(Camera HAL3)
HAL(Hardware Abstraction Layer)是 Android 框架与芯片厂商驱动之间的隔离层。Camera HAL3 使用 AIDL 接口定义(Android 13+,旧版为 HIDL):
bash
hardware/interfaces/camera/ # HAL 接口定义
关键接口:
aidl
// hardware/interfaces/camera/provider/aidl/ICameraProvider.aidl
interface ICameraProvider {
// 获取相机设备列表
CameraIdAndStreamCombination[] getCameraIdList();
// 获取相机设备接口
ICameraDevice getCameraDeviceInterface(in String cameraDeviceName);
}
// hardware/interfaces/camera/device/aidl/ICameraDevice.aidl
interface ICameraDevice {
// 获取相机特性
CameraMetadata getCameraCharacteristics();
// 打开相机
ICameraDeviceSession open(in ICameraDeviceCallback callback);
}
HAL3 与旧版 HAL1 的关键区别:从命令式改为 Request/Result 流水线模型------框架层发送 CaptureRequest,HAL 层流水线处理后返回 CaptureResult,完全异步。
2.5 驱动与硬件层
最底层与物理硬件交互:
- V4L2(Video4Linux2):Linux 内核标准视频驱动接口
- ISP(Image Signal Processor):图像信号处理器,负责 RAW → RGB 的图像处理
- Camera Sensor:CMOS/CCD 传感器,实际光电转换
bash
# 查看系统中的 V4L2 设备
adb shell ls /dev/video*
# 通常输出类似:/dev/video0 /dev/video1
三、Camera2 五大核心概念
理解了整体架构,深入看五个核心类的设计意图和关系。

3.1 CameraManager:相机的管理总入口
CameraManager 是系统服务,通过 getSystemService() 获取,作用是:
- 列举所有相机设备(前置、后置、外接 USB 相机)
- 查询相机静态特性(
CameraCharacteristics) - 打开指定相机设备
- 监听相机可用性变化
java
CameraManager manager = (CameraManager) context.getSystemService(Context.CAMERA_SERVICE);
// 1. 获取相机列表
String[] ids = manager.getCameraIdList();
for (String id : ids) {
CameraCharacteristics chars = manager.getCameraCharacteristics(id);
// 判断前/后置
Integer facing = chars.get(CameraCharacteristics.LENS_FACING);
if (facing == CameraCharacteristics.LENS_FACING_BACK) {
Log.d(TAG, "后置摄像头 ID: " + id);
}
}
// 2. 打开相机(异步,结果通过回调返回)
manager.openCamera(backCameraId, new CameraDevice.StateCallback() {
@Override
public void onOpened(@NonNull CameraDevice camera) {
// 相机已打开,camera 就是 CameraDevice 对象
mCameraDevice = camera;
createCaptureSession(); // 下一步:创建会话
}
@Override
public void onDisconnected(@NonNull CameraDevice camera) {
camera.close(); // 相机断开(被其他 App 抢占)
}
@Override
public void onError(@NonNull CameraDevice camera, int error) {
// 错误处理,error 值参见 CameraDevice.StateCallback.ERROR_*
camera.close();
}
}, backgroundHandler);
⚠️ 注意 :
openCamera()需要android.permission.CAMERA运行时权限。Android 12+ 还需要处理 隐私指示器(摄像头使用时顶部绿点)。
CameraManager 监听相机可用性(适用于多应用竞争场景):
java
manager.registerAvailabilityCallback(new CameraManager.AvailabilityCallback() {
@Override
public void onCameraAvailable(@NonNull String cameraId) {
// 相机变为可用(之前被其他 App 占用,现在释放了)
}
@Override
public void onCameraUnavailable(@NonNull String cameraId) {
// 相机变为不可用(被其他 App 抢占)
}
}, null);
3.2 CameraCharacteristics:静态特性查询
CameraCharacteristics 是相机的"说明书",保存了相机硬件的所有静态属性。它是只读的,在相机打开之前就能查询。
java
CameraCharacteristics chars = manager.getCameraCharacteristics(cameraId);
// 1. 硬件支持级别(能力越强,支持的功能越多)
int hwLevel = chars.get(CameraCharacteristics.INFO_SUPPORTED_HARDWARE_LEVEL);
// LEGACY(0) < LIMITED(0) < FULL(1) < LEVEL_3(3)
// Android 15 主流旗舰基本都是 FULL 或 LEVEL_3
// 2. 支持的输出格式和分辨率
StreamConfigurationMap map = chars.get(
CameraCharacteristics.SCALER_STREAM_CONFIGURATION_MAP);
// 查询 JPEG 拍照支持的尺寸
Size[] jpegSizes = map.getOutputSizes(ImageFormat.JPEG);
for (Size size : jpegSizes) {
Log.d(TAG, "支持 JPEG 尺寸: " + size.getWidth() + "x" + size.getHeight());
}
// 查询 YUV_420_888 预览支持的尺寸
Size[] yuvSizes = map.getOutputSizes(ImageFormat.YUV_420_888);
// 3. 焦距信息(用于判断广角/长焦)
float[] focalLengths = chars.get(CameraCharacteristics.LENS_INFO_AVAILABLE_FOCAL_LENGTHS);
// 4. 传感器物理尺寸(用于计算视角 FOV)
SizeF sensorSize = chars.get(CameraCharacteristics.SENSOR_INFO_PHYSICAL_SIZE);
// 5. 支持的 AE 模式(自动曝光)
int[] aeModes = chars.get(CameraCharacteristics.CONTROL_AE_AVAILABLE_MODES);
// 包含 CONTROL_AE_MODE_OFF(手动曝光)则支持手动控制
// 6. 最大数字变焦比例
float maxZoom = chars.get(CameraCharacteristics.SCALER_AVAILABLE_MAX_DIGITAL_ZOOM);
// Android 11+:逻辑相机下的物理相机列表(多摄系统)
Set<String> physicalCameras = chars.getPhysicalCameraIds();
硬件级别说明:
| 级别 | 常量值 | 典型能力 | 代表设备 |
|---|---|---|---|
LEGACY |
0 | 最基础,主要保证兼容性 | 旧设备软件模拟 |
LIMITED |
0 | 部分 Camera2 特性 | 中低端设备 |
FULL |
1 | 完整 Camera2 支持,含手动控制 | 主流旗舰 |
LEVEL_3 |
3 | 最高级别,支持 RAW 重处理等高级特性 | 旗舰+专业机型 |
3.3 CameraDevice:相机设备抽象
CameraDevice 代表一个已打开的物理(或逻辑)相机设备,职责是:
- 创建捕获会话(
CameraCaptureSession) - 创建捕获请求(
CaptureRequest.Builder) - 关闭设备(
close())
java
// 创建捕获请求的 Builder
// TEMPLATE_PREVIEW: 预览优化(持续 AF、AE)
// TEMPLATE_STILL_CAPTURE: 拍照优化(高质量,可能较慢)
// TEMPLATE_RECORD: 录像优化(稳定帧率优先)
// TEMPLATE_VIDEO_SNAPSHOT: 录像中插拍(兼顾帧率和质量)
// TEMPLATE_MANUAL: 完全手动控制
CaptureRequest.Builder builder = cameraDevice.createCaptureRequest(
CameraDevice.TEMPLATE_PREVIEW
);
// 添加输出目标(可以多个!这是 Camera2 相比 Camera1 的核心优势)
builder.addTarget(previewSurface); // 预览
builder.addTarget(imageReaderSurface); // 同时输出给 ImageReader
// 创建会话(Android 10- 的旧方式)
cameraDevice.createCaptureSession(outputSurfaces, stateCallback, handler);
// Android 10+ 的新方式(SessionConfiguration,更灵活)
SessionConfiguration sessionConfig = new SessionConfiguration(
SessionConfiguration.SESSION_REGULAR,
outputConfigurations,
executor,
stateCallback
);
cameraDevice.createCaptureSession(sessionConfig);
3.4 CameraCaptureSession:捕获会话
CameraCaptureSession 是 Camera2 最关键的概念之一,代表一次相机流配置:你告诉相机"我要这几路输出流,按这些参数输出",会话就建立了。
一次只能有一个活跃的会话(创建新会话会自动关闭旧会话)。
java
cameraDevice.createCaptureSession(Arrays.asList(previewSurface, imageReaderSurface),
new CameraCaptureSession.StateCallback() {
@Override
public void onConfigured(@NonNull CameraCaptureSession session) {
mCaptureSession = session;
// 设置重复请求(持续预览)
try {
CaptureRequest.Builder previewBuilder =
cameraDevice.createCaptureRequest(CameraDevice.TEMPLATE_PREVIEW);
previewBuilder.addTarget(previewSurface);
// ---- 核心 3A 设置 ----
// 自动对焦(连续对焦,适合视频预览)
previewBuilder.set(CaptureRequest.CONTROL_AF_MODE,
CaptureRequest.CONTROL_AF_MODE_CONTINUOUS_PICTURE);
// 自动曝光(开启防抖)
previewBuilder.set(CaptureRequest.CONTROL_AE_MODE,
CaptureRequest.CONTROL_AE_MODE_ON_AUTO_FLASH);
// 自动白平衡
previewBuilder.set(CaptureRequest.CONTROL_AWB_MODE,
CaptureRequest.CONTROL_AWB_MODE_AUTO);
// 启动重复请求(预览开始持续运行)
session.setRepeatingRequest(
previewBuilder.build(),
mCaptureCallback, // 每帧回调
mBackgroundHandler
);
} catch (CameraAccessException e) {
e.printStackTrace();
}
}
@Override
public void onConfigureFailed(@NonNull CameraCaptureSession session) {
// 会话配置失败(通常是请求的输出格式/尺寸组合不支持)
Log.e(TAG, "会话配置失败");
}
}, null);
两种请求方式的区别:
| 方式 | API | 用途 |
|---|---|---|
| 单次请求 | session.capture() |
拍一张照片 |
| 重复请求 | session.setRepeatingRequest() |
持续预览/录像 |
| 批量请求 | session.captureBurst() |
连拍 |
| 批量重复 | session.setRepeatingBurst() |
每帧用不同参数(罕见) |
3.5 CaptureRequest & CaptureResult:请求与结果
这是 Camera2 Pipeline 模型的核心:你发送 Request,硬件处理后返回 Result。
java
// ===== CaptureRequest:控制每一帧的拍摄参数 =====
CaptureRequest.Builder builder = session.getDevice()
.createCaptureRequest(CameraDevice.TEMPLATE_STILL_CAPTURE);
// 手动 ISO(感光度)
builder.set(CaptureRequest.SENSOR_SENSITIVITY, 800); // ISO 800
// 手动快门速度(纳秒)
builder.set(CaptureRequest.SENSOR_EXPOSURE_TIME, 1_000_000_000L / 60); // 1/60s
// 手动对焦距离(0=无穷远,1/最近对焦距离=最近)
builder.set(CaptureRequest.LENS_FOCUS_DISTANCE, 0.0f); // 无穷远
// JPEG 质量
builder.set(CaptureRequest.JPEG_QUALITY, (byte) 95);
// 数字变焦(Android 11+ 推荐用 CONTROL_ZOOM_RATIO,旧版用 SCALER_CROP_REGION)
builder.set(CaptureRequest.CONTROL_ZOOM_RATIO, 2.0f); // 2x 变焦
session.capture(builder.build(), captureCallback, handler);
java
// ===== CaptureResult:每帧的实际拍摄结果 =====
CameraCaptureSession.CaptureCallback captureCallback =
new CameraCaptureSession.CaptureCallback() {
@Override
public void onCaptureCompleted(@NonNull CameraCaptureSession session,
@NonNull CaptureRequest request,
@NonNull TotalCaptureResult result) {
// 实际 ISO(可能与请求不同,因为 AE 算法可能覆盖)
Integer iso = result.get(CaptureResult.SENSOR_SENSITIVITY);
// 实际快门速度(纳秒)
Long exposureTime = result.get(CaptureResult.SENSOR_EXPOSURE_TIME);
// AF 状态(是否对焦成功)
Integer afState = result.get(CaptureResult.CONTROL_AF_STATE);
if (afState == CaptureResult.CONTROL_AF_STATE_FOCUSED_LOCKED) {
Log.d(TAG, "对焦成功!");
}
// 帧的精确时间戳(纳秒,来自传感器)
Long timestamp = result.get(CaptureResult.SENSOR_TIMESTAMP);
}
@Override
public void onCaptureFailed(@NonNull CameraCaptureSession session,
@NonNull CaptureRequest request,
@NonNull CaptureFailure failure) {
Log.e(TAG, "捕获失败: " + failure.getReason());
}
};
💡 Request 和 Result 的关系:Request 是你的"期望",Result 是硬件实际执行的"结果"。两者可能不同------例如你请求 ISO 200,但当前光线太暗,AE 算法将实际 ISO 提升到了 800,Result 里就会反映真实值。
四、Camera2 Pipeline 模型深度解析
Camera2 真正的精髓在于其 Pipeline(流水线) 模型。理解这个模型,才能真正掌握 Camera2。
4.1 什么是 Pipeline 模型
Camera2 将相机的工作抽象成一条流水线:
ini
应用层: CaptureRequest ──→ [Camera Pipeline] ──→ CaptureResult + 帧数据
↑
(硬件按Pipeline顺序处理)
1. 传感器曝光
2. RAW数据读取
3. ISP处理(去噪、锐化、色彩)
4. 编码输出(JPEG/YUV)
5. 元数据生成(CaptureResult)
关键特性:
- 多帧并发:Pipeline 中可以同时有多个请求在处理(类似 CPU 的指令流水线)
- 精确时序:每帧都有纳秒级时间戳,可以与音频帧精确同步
- 多路输出:一个 Request 可以同时产生 JPEG(拍照)+ YUV(预览)+ RAW(原始数据)
4.2 多路输出流
Camera2 支持同时配置多路输出流,这是其最重要的能力之一:
java
// 典型的三路输出配置:预览 + 拍照 + 视频录制
List<Surface> outputs = new ArrayList<>();
// 1. 预览 Surface(TextureView 或 SurfaceView)
SurfaceTexture surfaceTexture = textureView.getSurfaceTexture();
surfaceTexture.setDefaultBufferSize(previewWidth, previewHeight);
Surface previewSurface = new Surface(surfaceTexture);
outputs.add(previewSurface);
// 2. 拍照 ImageReader(接收 JPEG 数据)
ImageReader jpegImageReader = ImageReader.newInstance(
4032, 3024, // 12MP 分辨率
ImageFormat.JPEG,
2 // Buffer 数量(推荐 2 个,避免卡顿)
);
jpegImageReader.setOnImageAvailableListener(reader -> {
Image image = reader.acquireLatestImage();
// 处理 JPEG 数据...
image.close(); // 必须 close!否则 Buffer 泄漏
}, handler);
outputs.add(jpegImageReader.getSurface());
// 3. 视频录制 Surface(MediaRecorder 或 MediaCodec 提供)
Surface recorderSurface = mediaRecorder.getSurface();
outputs.add(recorderSurface);
// 创建会话(同时支持三路输出)
cameraDevice.createCaptureSession(outputs, stateCallback, handler);
⚠️ 多路流约束 :并非任意组合都被支持。
SCALER_STREAM_CONFIGURATION_MAP定义了哪些格式+尺寸的组合可以同时使用。一般规则:1路大分辨率JPEG + 1路预览 + 1路录像是旗舰机型都支持的标准配置。
4.3 Repeating Request 的精确控制
连续预览的本质是一个无限循环的 setRepeatingRequest,每一帧都执行一次:
vbscript
帧1: Request₁ → [Pipeline] → Result₁ + YUVFrame₁
帧2: Request₂ → [Pipeline] → Result₂ + YUVFrame₂ (Request₂ 通常与Request₁相同)
帧3: Request₃ → [Pipeline] → Result₃ + YUVFrame₃
...
当需要改变参数(例如用户点击屏幕触发对焦)时:
java
// 触摸对焦示例
// Step 1: 触发 AF(发一帧特殊 Request)
CaptureRequest.Builder afBuilder =
cameraDevice.createCaptureRequest(CameraDevice.TEMPLATE_PREVIEW);
afBuilder.addTarget(previewSurface);
afBuilder.set(CaptureRequest.CONTROL_AF_TRIGGER,
CaptureRequest.CONTROL_AF_TRIGGER_START); // ← 触发 AF
// 设置 AE/AF 检测区域(触摸位置)
afBuilder.set(CaptureRequest.CONTROL_AF_REGIONS, afRegions);
afBuilder.set(CaptureRequest.CONTROL_AE_REGIONS, aeRegions);
session.capture(afBuilder.build(), captureCallback, handler);
// Step 2: 等待 AF 收敛(通过 captureCallback 监听 CONTROL_AF_STATE)
// Step 3: AF 锁定后拍照
五、Android 15 视频/相机新特性
5.1 Ultra HDR 照片支持
Android 15 正式将 Ultra HDR 带入主流,这是一种可以同时包含 SDR 和 HDR 元数据的 JPEG 格式:
java
// 检查是否支持 Ultra HDR 拍照
StreamConfigurationMap map = chars.get(
CameraCharacteristics.SCALER_STREAM_CONFIGURATION_MAP);
boolean supportsUltraHdr = false;
int[] formats = map.getOutputFormats();
for (int format : formats) {
if (format == ImageFormat.JPEG_R) { // JPEG_R 就是 Ultra HDR
supportsUltraHdr = true;
break;
}
}
// 使用 Ultra HDR 拍照
if (supportsUltraHdr) {
ImageReader ultraHdrReader = ImageReader.newInstance(
width, height,
ImageFormat.JPEG_R, // Ultra HDR 格式
2
);
builder.addTarget(ultraHdrReader.getSurface());
}
Ultra HDR 照片在 SDR 显示器上与普通 JPEG 一样显示,但在 HDR 显示器(如旗舰手机屏幕)上可以呈现更高动态范围,且文件兼容性极好(标准 JPEG 格式的超集)。
5.2 10-bit 视频录制(LOG 格式)
Android 15 全面支持 10-bit HDR 视频录制,支持 HLG(Hybrid Log-Gamma)和 HDR10 格式:
java
// 查询是否支持 10-bit 视频
boolean supports10Bit = false;
int[] capabilities = chars.get(
CameraCharacteristics.REQUEST_AVAILABLE_CAPABILITIES);
for (int cap : capabilities) {
if (cap == CameraCharacteristics.REQUEST_AVAILABLE_CAPABILITIES_DYNAMIC_RANGE_TEN_BIT) {
supports10Bit = true;
break;
}
}
if (supports10Bit) {
// 配置 10-bit HLG 输出
OutputConfiguration outputConfig = new OutputConfiguration(recorderSurface);
outputConfig.setDynamicRangeProfile(
DynamicRangeProfiles.HLG10 // 或 HDR10, HDR10_PLUS
);
}
10-bit 视频录制对硬件编解码器要求更高,需要同时满足:
- 相机传感器支持 10-bit 输出
- ISP 支持 10-bit 数据通路
- 硬件视频编码器支持 10-bit H.265/AV1
5.3 多摄像头并发支持
Android 11 引入、Android 15 完善的多摄并发(ConcurrentCamera),允许同时开启前置和后置摄像头:
java
// 查询支持并发使用的相机组合
Set<Set<String>> concurrentCameraIds = manager.getConcurrentCameraIds();
for (Set<String> cameraSet : concurrentCameraIds) {
Log.d(TAG, "这些相机可同时使用: " + cameraSet);
// 通常输出: ["0", "1"] 表示前后置可同时用(用于视频通话等场景)
}
5.4 夜景增强与 Extension API
Android 15 的 Camera Extensions API 提供了系统级的夜景、HDR、散景等拍摄模式,不再需要 App 自己做 ML 处理:
java
// 使用 Camera Extensions
CameraExtensionSession.StateCallback extensionStateCallback = ...;
// 创建 Extension Session(替代普通 CameraCaptureSession)
cameraDevice.createExtensionSession(
new CameraExtensionSessionConfiguration(
CameraExtensionCharacteristics.EXTENSION_NIGHT, // 夜景模式
outputList,
executor,
extensionStateCallback
)
);
六、调试工具速查
6.1 查看相机服务状态
bash
# 查看 CameraService 完整状态(相机列表、当前会话、帧率等)
adb shell dumpsys media.camera
# 查看已打开的相机列表和客户端
adb shell dumpsys media.camera | grep -A 5 "Camera module"
# 查看当前活跃的捕获会话
adb shell dumpsys media.camera | grep -A 20 "Active clients"
# 查看相机性能统计(帧率、延迟)
adb shell dumpsys media.camera | grep -E "fps|latency|duration"
6.2 实时日志过滤
bash
# 过滤 Camera2 关键日志
adb logcat -s CameraService:V Camera3Device:V CameraDeviceClient:V
# 过滤相机打开/关闭事件
adb logcat | grep -E "openCamera|closeCamera|createSession"
# 过滤 CaptureRequest 发送
adb logcat | grep -E "CaptureRequest|CaptureResult|setRepeatingRequest"
6.3 Systrace 相机性能分析
bash
# 使用 Systrace 捕获相机帧率数据
adb shell atrace -b 16384 -t 10 camera hal | gzip > /tmp/camera-trace.gz
# 或使用 Perfetto(更现代的方案)
adb shell perfetto \
--config - --txt \
--out /data/local/tmp/camera-trace.pb \
<<EOF
buffers: { size_kb: 32768 }
data_sources {
config {
name: "linux.ftrace"
ftrace_config {
ftrace_events: "camera/camera_capture_request_new"
ftrace_events: "camera/camera_capture_result_received"
}
}
}
duration_ms: 5000
EOF
6.4 常见问题诊断
问题1:onConfigureFailed 会话配置失败
bash
# 查看失败原因
adb logcat | grep -E "createCaptureSession|ConfigureFailed|stream config"
# 常见原因:
# 1. 请求的输出格式+尺寸组合不被硬件支持
# 2. 同时配置的流数量超出硬件限制
# 3. Surface 在创建会话时已失效(SurfaceTexture/SurfaceHolder 已销毁)
问题2:预览画面黑屏
bash
# 检查会话是否正常启动
adb shell dumpsys media.camera | grep -A 10 "Active streams"
# 常见原因:
# 1. setRepeatingRequest 没有调用
# 2. Surface 尺寸与 SurfaceTexture 设置不匹配
# 3. 相机权限被拒绝
问题3:拍照延迟过高(快门慢)
bash
# 查看 Camera3Device 的请求队列深度
adb shell dumpsys media.camera | grep -E "In-flight|requestId"
# 优化方案:
# 1. 预先触发 AF/AE(precapture sequence)
# 2. 使用 ZSL(Zero Shutter Lag)模式
# 3. 降低预览分辨率减少管线处理压力
七、Camera2 的设计思想总结
回顾 Camera2 的整体设计,有几个思想值得反复品味:
7.1 Pipeline 胜于命令
Camera1 是"发命令、等结果",Camera2 是"描述管道、让数据流动"。Pipeline 模型天然支持异步、多路输出和精确时序控制,这是现代相机 APP(专业相机、视频创作)所必需的。
7.2 分层解耦
- Java 层:API 契约,面向开发者
- Native 层:性能关键路径,C++ 实现
- HAL 层:硬件解耦,芯片商自由实现
这种分层确保了 Android 相机框架不依赖特定硬件,同时性能也不会被 Java 层拖累。
7.3 元数据驱动
CaptureRequest 和 CaptureResult 本质上都是 Key-Value 元数据表,相机参数通过元数据流传递而非硬编码接口。这带来了极强的可扩展性------新的控制参数(如 Ultra HDR、10-bit 等)只需新增 Key,无需修改接口。
总结
本文介绍了 Android 15 Camera2 API 的整体架构和核心概念:
- Camera2 vs Camera1:从命令式→流水线式,支持多路输出、精细 3A 控制、纳秒级时间戳
- 五层架构:Java API → Java Framework → CameraService(Native)→ Camera HAL3 → 驱动/硬件
- 五大核心类 :
CameraManager:相机管理入口CameraCharacteristics:静态特性查询CameraDevice:已打开的相机设备CameraCaptureSession:流配置和请求发送CaptureRequest/Result:每帧的控制参数和实际结果
- Pipeline 模型:多路并发流水线,多路输出同时支持
- Android 15 新特性:Ultra HDR、10-bit 视频、多摄并发、Extension API 夜景增强
理解 Camera2 架构,是后续深入 CameraService 资源管理、相机预览流程、HAL3 接口的基础。
参考资料
- Android Camera Architecture --- 官方架构文档
- Camera2 API Overview --- Android 开发者文档
frameworks/base/core/java/android/hardware/camera2/CameraManager.java--- CameraManager 源码frameworks/base/core/java/android/hardware/camera2/CameraDevice.java--- CameraDevice 源码frameworks/base/core/java/android/hardware/camera2/CameraCaptureSession.java--- Session 源码frameworks/av/services/camera/libcameraservice/CameraService.cpp--- CameraService Native 实现