Camera2 API 如何与 HAL3 自动适配

关键词:
Camera2、HAL3、自动适配、StreamConfigurationMap、CaptureRequest、CameraMetadata、SessionConfiguration、DeviceCallback、动态协商

摘要:
Android Camera 架构中,Camera2 API 是应用层与底层 HAL3 驱动间的中介抽象,其核心机制是将高层标准化请求(如 Preview、ImageCapture)自动转化为兼容各厂商 HAL3 的调用组合,并基于设备能力动态构建流配置与 Metadata 协议。本文基于实际项目调试经验,系统解析 Camera2 如何完成与 HAL3 的自动适配,包括请求构建、能力协商、Buffer 流配置、Metadata 回传与错误处理等关键流程,帮助开发者在面对多平台相机适配与兼容性问题时具备工程实操能力。


目录

  1. Camera 架构回顾:Camera2 × HAL3 的职责分层与交互路径
  2. HAL3 自动适配的触发时机与关键机制总览
  3. 能力查询:如何通过 CameraCharacteristics 动态获取 HAL3 能力
  4. StreamConfigurationMap 与 UseCase 配置的适配逻辑
  5. CaptureRequest 构建过程与参数标准化封装策略
  6. 请求发送与 HAL3 接口映射路径详解
  7. Metadata 回传链路解析:Result → App Callback 的闭环
  8. 工程实战建议:跨平台稳定性优化 × 错误容错策略 × Trace 调试入口

一、Camera 架构回顾:Camera2 × HAL3 的职责分层与交互路径

Android Camera 系统采用典型的层次式架构,Camera2 API 与 HAL3 驱动之间通过 HIDLAIDL 接口桥接,以实现跨厂商平台的图像能力抽象与请求传递。理解这一分层结构是掌握 HAL3 自动适配机制的基础。


1.1 系统分层结构与功能职责
[App 层]
 └── Camera2 API(CameraManager / CameraDevice / CaptureRequest)
      ↓
[Framework 层]
 └── CameraService
      ↓
[HAL 层(Vendor Implementation)]
 └── Camera HAL3(ICameraDeviceSession, ICameraDeviceCallback)
      ↓
[驱动 & ISP 层]
 └── Sensor, ISP, DMA, JPEG Codec, AE/AF/AWB Unit
  • Camera2 API:
    • 对外提供标准请求接口(Preview、拍照、变焦、控制参数)
    • 管理生命周期与会话绑定逻辑(CameraDeviceCaptureSession
    • 提供设备能力查询接口(CameraCharacteristics
  • CameraService:
    • 统一管理多摄设备、资源调度、权限控制
    • 建立 Camera2 到 HAL3 的会话桥接(ICameraDeviceSession)
  • Camera HAL3:
    • 实现 processCaptureRequest()configureStreams() 等 HAL 接口
    • 执行具体的 Sensor 控制、流配置、Buffer 处理
    • 通过回调返回 CaptureResultShutterNotify 等状态

1.2 Camera2 到 HAL3 的交互路径简述

以一次 Preview 请求为例:

  1. App 调用 CameraDevice.createCaptureSession() 绑定 Surface → 生成 SessionConfiguration
  2. CameraService 通过 Binder 将请求转为 HAL3 的 configureStreams()
  3. App 创建 CaptureRequest,调用 capture() 触发图像采集
  4. Framework 封装请求为 HALRequest,传递给 processCaptureRequest() 接口
  5. HAL3 驱动执行图像采集,填充 buffer,回调 processCaptureResult() 给 CameraService
  6. Framework 封装为 TotalCaptureResult,上报给 App 的 CameraCaptureCallback

1.3 HAL3 架构设计初衷:标准化 × 可拓展 × 高性能
  • 不再由厂商提供 Java SDK,转为提供标准 HAL 接口,降低集成复杂度
  • 支持并发流配置、动态请求组合、Metadata 管理能力
  • 提供 InputStream, Reprocessing, ZSL 等高阶场景支持

因此 Camera2 的所有能力都需通过 CameraCharacteristics 与动态请求协商方式,自动适配 HAL3 提供的能力边界。


二、HAL3 自动适配的触发时机与关键机制总览

Camera2 并不会假设所有设备行为一致,而是通过 设备能力协商 + 请求封装策略 + Metadata 透传 的机制,在运行时动态适配 HAL3 的具体实现差异。这个过程完全由 Framework 自动完成,开发者无需感知 HAL 细节。


2.1 适配的核心触发时机
时机对应动作适配内容
CameraManager.openCamera()获取设备能力读取 CameraCharacteristics
CameraDevice.createCaptureSession()配置图像流调用 configureStreams(),传入 Surface 配置
CameraCaptureSession.capture() / setRepeatingRequest()请求提交CaptureRequest 组装为 HAL Request
HAL 回调 processCaptureResult()结果接收将 HAL metadata 封装为 TotalCaptureResult 上报 App

2.2 自动适配的关键能力模块
  1. 流能力协商(StreamConfigurationMap)

    Camera2 查询 CameraCharacteristics.SCALER_STREAM_CONFIGURATION_MAP,动态识别:

    • 支持的输出格式(YUV、JPEG、RAW、DEPTH 等)
    • 各格式下支持的分辨率
    • 是否支持 InputStream、ZSL、私有格式
  2. 请求参数支持范围(Request Keys)

    Camera2 读取:

    • REQUEST_AVAILABLE_CAPABILITIES:如 MANUAL_SENSOR、RAW、READ_SENSOR_SETTINGS
    • CONTROL_AE_AVAILABLE_MODESLENS_INFO_AVAILABLE_FOCAL_LENGTHS 等 key/value 范围
    • 自动决定是否启用手动模式、HDR、对焦模式等
  3. Metadata key 协议转换

    所有请求与回调参数都通过 CameraMetadata(key/value)管理:

    • App → Request.set(key, value)
    • Framework → HAL3Request → Metadata 构建
    • HAL → processCaptureResult → Metadata 返回
    • Framework → Result → key 解包后分发给 App

    Camera2 会根据 availableKeys 列表限制 App 可用参数,防止传入不支持的配置。

  4. 请求节奏与流优化策略

    Camera2 会依据流配置特征、Surface 类型、Usage Flags 等信息:

    • 判断是否开启单一流优化(如 PREVIEW + YUV 复用)
    • 自动设置 TEMPLATE_PREVIEW, TEMPLATE_STILL_CAPTURE 模板以匹配 HAL 预设参数组合
    • 结合 SessionConfiguration 配置流优先级、组合顺序等

2.3 动态请求封装逻辑路径
CaptureRequest.Builder builder = cameraDevice.createCaptureRequest(CameraDevice.TEMPLATE_PREVIEW);
builder.addTarget(surface);
builder.set(CONTROL_AF_MODE, CONTROL_AF_MODE_CONTINUOUS_PICTURE);
...
cameraCaptureSession.setRepeatingRequest(builder.build(), callback, handler);

框架在构建 Request 时,自动校验:

  • 所使用 key 是否包含在 CameraCharacteristics.getAvailableCaptureRequestKeys()
  • 若不支持则抛出异常或自动 fallback 为默认值

最终打包为 camera_metadata_t 结构,传入 HAL 层。


三、能力查询:如何通过 CameraCharacteristics 动态获取 HAL3 能力

在 Camera2 架构下,系统在打开相机设备时会自动从 HAL3 层拉取该设备的能力描述,通过 CameraCharacteristics 暴露给上层,开发者或 Framework 可依据这些能力信息进行自动适配与策略决策。


3.1 CameraCharacteristics 的获取路径

使用 Camera2 API 打开相机时,系统通过 CameraManager 查询设备列表及其能力:

val manager = context.getSystemService(Context.CAMERA_SERVICE) as CameraManager
val cameraIdList = manager.cameraIdList
val characteristics = manager.getCameraCharacteristics(cameraId)

内部会触发一次与 HAL3 的元数据同步,Framework 将 static_metadata 封装为 CameraMetadataNative 并上报给应用。


3.2 常见能力字段解析
字段名称类型说明
CameraCharacteristics.REQUEST_AVAILABLE_CAPABILITIESint[]相机支持的 HAL3 功能模块,如 RAW, ZSL, MANUAL_SENSOR
CameraCharacteristics.SCALER_STREAM_CONFIGURATION_MAPStreamConfigurationMap支持的分辨率、格式、流类型组合
CONTROL_AF_AVAILABLE_MODESint[]支持的自动对焦模式(如 AUTO, CONTINUOUS_PICTURE
LENS_INFO_MINIMUM_FOCUS_DISTANCEfloat最小对焦距离,若为 0 则表示固定焦
SENSOR_INFO_EXPOSURE_TIME_RANGERange<Long>曝光时间支持范围,手动拍摄必要条件
JPEG_AVAILABLE_THUMBNAIL_SIZESSize[]拍照后缩略图尺寸支持表
INFO_SUPPORTED_HARDWARE_LEVELint硬件支持等级(LEGACY, LIMITED, FULL, LEVEL_3)决定能力上限

3.3 判断设备是否支持高级功能

可结合以下逻辑判断:

val capabilities = characteristics.get(
    CameraCharacteristics.REQUEST_AVAILABLE_CAPABILITIES)

val isRawSupported = capabilities?.contains(
    CameraCharacteristics.REQUEST_AVAILABLE_CAPABILITIES_RAW) == true

val supportsManualExposure = capabilities?.contains(
    CameraCharacteristics.REQUEST_AVAILABLE_CAPABILITIES_MANUAL_SENSOR) == true

val isHardwareLevelFull = characteristics.get(
    CameraCharacteristics.INFO_SUPPORTED_HARDWARE_LEVEL) ==
    CameraCharacteristics.INFO_SUPPORTED_HARDWARE_LEVEL_FULL

只有当设备支持 FULL 级别硬件 + 对应能力字段,才可以启用手动控制、RAW 输出、ZSL 复用等模式。


3.4 利用能力信息进行动态适配

开发者可根据读取结果:

  • 动态启用 UseCase 模式:
    • 若支持 MANUAL_SENSOR → 切换为手动曝光流程
    • 若支持 RAW → 增加 RAW 流配置或 CaptureRequest 输出 target
  • 调整 UI 功能开关:
    • 若不支持缩放、闪光、HDR、ZSL 等 → 动态隐藏或禁用前端控件
  • 构建兼容策略:
    • 当多个设备能力差异明显时,可将 CameraCharacteristics 持久化作为设备能力 Cache,提升启动效率

四、StreamConfigurationMap 与 UseCase 配置的适配逻辑

在 Camera2 中,StreamConfigurationMap 是 HAL3 自动适配的核心数据结构,它定义了当前相机所支持的所有流组合配置,包括不同格式下的分辨率、帧率、输入输出能力等,直接影响 Surface 绑定、CaptureSession 创建与 CaptureRequest 的正确执行。


4.1 获取 StreamConfigurationMap
val streamMap = characteristics.get(
    CameraCharacteristics.SCALER_STREAM_CONFIGURATION_MAP)

4.2 常用接口与用途
方法返回值用途
getOutputSizes(ImageFormat.YUV_420_888)Size[]支持 YUV 输出分辨率列表(如用于 ImageReader)
getOutputSizes(SurfaceTexture::class.java)Size[]支持预览流尺寸(用于 TextureView)
isOutputSupportedFor(int format)Boolean某种格式是否支持输出
getInputSizes(ImageFormat.YUV_420_888)Size[]是否支持 Reprocessing 流
getHighSpeedVideoFpsRanges()Range<Int>[]高帧率视频支持范围
getOutputMinFrameDuration()Long每种格式和尺寸下的最小输出间隔(用于帧率控制)

4.3 动态选择最佳尺寸与配置逻辑(实战建议)

以预览流为例:

val previewSizes = streamMap?.getOutputSizes(SurfaceTexture::class.java)
val optimalSize = previewSizes?.filter {
    it.width <= 1920 && it.height <= 1080
}?.maxByOrNull { it.width * it.height }

以拍照流为例:

val captureSizes = streamMap?.getOutputSizes(ImageFormat.JPEG)
val maxResolution = captureSizes?.maxByOrNull { it.width * it.height }

4.4 Surface 与流配置的匹配策略

在调用 CameraDevice.createCaptureSession() 时,Framework 会:

  1. 根据每个 Surface 的 buffer format / size / usage 反推目标流类型
  2. 匹配 StreamConfigurationMap 中的合法输出组合
  3. 构造 StreamConfiguration 传入 HAL → 调用 configureStreams()

若任一 Surface 配置在 Map 中找不到匹配,将导致 Session 创建失败,返回 ERROR_STREAM_CONFIGURE_FAIL


4.5 多 UseCase 流并发配置场景

当同时存在多个输出目标(如 Preview + JPEG + ImageAnalysis)时:

  • 系统会联合分析每个输出流的格式/尺寸
  • 选择兼容的 buffer 分配方案与处理 pipeline
  • HAL3 实现需支持 MAX_CONCURRENT_STREAMS 才能并发处理

实战建议:

  • 控制输出流不超过 3 路,避免因 HAL 限制导致 Stream 配置失败
  • 尽量避免高分辨率流 + 低延迟流混用(如 4K + Preview),需在平台上实测验证

五、CaptureRequest 构建过程与参数标准化封装策略

在 Camera2 架构中,CaptureRequest 是图像请求的核心结构,封装了用户希望如何控制拍摄行为的全部参数(如 AE、AF、AWB、曝光时间、目标 Surface 等)。Camera2 通过一套统一的构建接口与参数校验机制,将应用层的请求转换为底层 HAL3 能接受的格式,完成跨平台的行为统一。


5.1 CaptureRequest 的创建流程

标准构建流程如下:

val builder = cameraDevice.createCaptureRequest(CameraDevice.TEMPLATE_PREVIEW)
builder.addTarget(previewSurface)
builder.set(CaptureRequest.CONTROL_AF_MODE, CONTROL_AF_MODE_CONTINUOUS_PICTURE)
val request = builder.build()

框架内部执行如下动作:

  1. 选定一个 RequestTemplate(如 TEMPLATE_PREVIEW
  2. 初始化一个包含默认值的 CaptureRequest.Builder
  3. 加入 Surface 目标(必须与已配置流匹配)
  4. 开发者通过 set() 填入自定义控制参数
  5. 调用 build() → 封装为最终 CaptureRequest

5.2 常见模板类型与应用场景
模板说明适用场景
TEMPLATE_PREVIEW实时预览流,低延迟、自动曝光/对焦普通预览
TEMPLATE_STILL_CAPTURE拍照帧,高质量 JPEG 输出,开启 3A 精度拍照
TEMPLATE_RECORD视频录制流,稳定帧率Video
TEMPLATE_MANUAL手动控制全部参数手动曝光
TEMPLATE_ZERO_SHUTTER_LAGZSL 帧复用模式拍照低延迟优化

模板本质上是 Framework 提供的一组 HAL 端默认值组合,在不设置参数时能确保 HAL3 正常执行。


5.3 参数注入策略与封装机制

Camera2 使用 CaptureRequest.set(key, value) 来配置所有参数。内部通过:

  • 参数 Key 类型检查(仅允许设置设备支持的 Key)
  • 类型与取值范围校验
  • 自动 fallback 或抛出异常(如设置了不支持的对焦模式)

示例:设置自动对焦模式 + 曝光模式 + 闪光控制

builder.set(CaptureRequest.CONTROL_AF_MODE, CONTROL_AF_MODE_CONTINUOUS_PICTURE)
builder.set(CaptureRequest.CONTROL_AE_MODE, CONTROL_AE_MODE_ON)
builder.set(CaptureRequest.FLASH_MODE, FLASH_MODE_OFF)

5.4 标准化封装建议(实战经验)
  1. 构建统一 Request 工具类

    将常见配置封装为函数,提高稳定性与复用度:

    fun applyStandardPreviewParams(builder: CaptureRequest.Builder) {
        builder.set(CONTROL_AF_MODE, CONTROL_AF_MODE_CONTINUOUS_PICTURE)
        builder.set(CONTROL_AWB_MODE, CONTROL_AWB_MODE_AUTO)
        builder.set(CONTROL_AE_MODE, CONTROL_AE_MODE_ON)
    }
    
  2. 根据 CameraCharacteristics 动态裁剪参数

    val supportedAfModes = characteristics.get(CONTROL_AF_AVAILABLE_MODES)
    if (supportedAfModes?.contains(CONTROL_AF_MODE_CONTINUOUS_PICTURE) == true) {
        builder.set(CONTROL_AF_MODE, CONTROL_AF_MODE_CONTINUOUS_PICTURE)
    }
    
  3. 避免动态请求导致 HAL 重建

    对于周期性 Request(如 Preview),参数应预设好,避免运行时频繁变更 Surface 或 stream 格式,造成 configureStreams() 重建。


六、请求发送与 HAL3 接口映射路径详解

CaptureRequest 构建完成后,应用通过 CameraCaptureSession 提交该请求,最终传递到底层 HAL3 的 processCaptureRequest() 接口。整个路径涉及多层封装、线程调度与 Metadata 映射,是理解 Camera2 与 HAL3 交互机制的核心。


6.1 请求提交路径结构图(简化)
App → CaptureRequest
    ↓
CameraCaptureSession.capture()
    ↓
CameraDeviceClient.submitRequests()
    ↓
Camera3Device::submitRequestList()
    ↓
constructHalRequest()
    ↓
CameraHal::processCaptureRequest()

6.2 单帧与重复请求的处理方式
  • 单帧请求(如拍照)

    session.capture(request, callback, handler)
    

    仅执行一次,HAL 处理完返回结果后即结束。

  • 重复请求(如 Preview)

    session.setRepeatingRequest(request, callback, handler)
    

    持续提交该 CaptureRequest,由 HAL 重复执行直到被取消。

Framework 内部为每帧维护 Request ID、Frame Number、Surface 映射等元数据,确保请求结果能与回调一一对应。


6.3 HAL 接收的最终结构:processCaptureRequest

在 HAL3 接口中:

status_t processCaptureRequest(const std::vector<HalRequest>& requests);

每个 HalRequest 包括:

  • metadata: 由 CaptureRequest 转换而来(所有 set 的 Key → HAL Key ID)
  • outputBuffers: 输出流的 buffer handle(Surface 映射)
  • frameNumber: 用于与回调结果对齐
  • inputBuffer: 可选,用于 reprocessing(如 YUV → JPEG)

6.4 HAL 回调路径简述(Metadata × Buffer 返回)

HAL 图像采集完成后,调用:

processCaptureResult(const camera3_capture_result_t *result)
notify(const camera3_notify_msg_t *msg)

Framework 将其转换为:

onCaptureCompleted(CaptureRequest request, TotalCaptureResult result)
onCaptureFailed(CaptureFailure failure)
onCaptureStarted()

该回调最终由 App 层注册的 CameraCaptureCallback 接收,实现拍照完成、帧落地等事件响应。


6.5 工程建议与性能考量
  • 对于高频请求(如 setRepeatingRequest()),应使用同一实例重用,以避免内部重复构建 Request 结构。
  • 请求合并(Burst)时,可将多个 CaptureRequest 放入列表,提高吞吐量。
  • 多个 Surface 目标绑定同一 Request 时,需确保尺寸与格式兼容。

七、Metadata 回传链路解析:Result → App Callback 的闭环

在 Camera2 与 HAL3 的交互体系中,Metadata 是图像状态与控制信号的桥梁。从 HAL 输出图像帧开始,经过 HAL → Framework → App 多级传递,最终由应用通过 CameraCaptureCallback 获取。这一链路不仅传递图像处理结果,还承担 AE/AF/AWB 状态、拍照时序、帧同步、异常报告等任务,是实现闭环控制与调试定位的关键。


7.1 HAL3 回传的 Metadata 构成

在 HAL 中,图像完成采集后,会调用:

camera3_capture_result_t {
    uint32_t frame_number;
    const camera_metadata_t *result;  // 包含所有 metadata key
    buffer_handle_t *output_buffers[];
}

其中 result 是关键部分,由 HAL 按照 metadata schema 构建,填入如:

  • android.control.afState
  • android.control.aeState
  • android.sensor.timestamp
  • android.jpeg.quality
  • android.lens.focusDistance

7.2 Framework 封装为 CaptureResult / TotalCaptureResult

Framework 会将 HAL 回传数据解析为 Java 对象,主要包括:

  • CaptureResult:标准回调结构,包含当前帧的 Metadata 信息(但不含完整请求)
  • TotalCaptureResult:包括原始请求、frame number、metadata、output buffer 等全部信息

在拍照流、ZSL、Burst 拍摄等场景中,会优先返回 TotalCaptureResult,用于高质量控制与对齐。


7.3 应用层回调路径

开发者通过注册如下接口接收回调:

val callback = object : CameraCaptureSession.CaptureCallback() {
    override fun onCaptureStarted(session: CameraCaptureSession, request: CaptureRequest, timestamp: Long, frameNumber: Long) {
        ...
    }

    override fun onCaptureCompleted(session: CameraCaptureSession, request: CaptureRequest, result: TotalCaptureResult) {
        val aeState = result.get(CaptureResult.CONTROL_AE_STATE)
        val afState = result.get(CaptureResult.CONTROL_AF_STATE)
        ...
    }

    override fun onCaptureFailed(session: CameraCaptureSession, request: CaptureRequest, failure: CaptureFailure) {
        ...
    }
}

所有 metadata key 都通过:

result.get(CaptureResult.KEY)

方式获取,类型安全且结构清晰。


7.4 多帧回调的关联机制

Framework 会维护 frameNumberrequest 的映射表,并追踪回调进度,确保每个请求对应一个完整的结果闭环。

  • 若多个帧共享同一个 setRepeatingRequest(),则 request 为同一个实例,frame number 递增
  • 若某帧被 HAL drop,Framework 会通过 onCaptureFailed() 主动告知应用

7.5 Metadata 回传常见用途
Key用途
CONTROL_AF_STATE自动对焦是否完成,是否失败
CONTROL_AE_STATE曝光状态,是否触发或收敛
SENSOR_TIMESTAMP图像曝光的时间戳(用于帧同步)
JPEG_ORIENTATION拍照图像的旋转方向
STATISTICS_LENS_SHADING_MAP镜头阴影校正数据(调试 ISP 用)

八、工程实战建议:跨平台稳定性优化 × 错误容错策略 × Trace 调试入口

在实际工程中,Camera2 × HAL3 的适配往往面临平台差异大、驱动行为不一致、Session 构建失败、帧丢失等问题。为保证系统稳定性与图像流顺畅,需从策略设计、容错机制与调试手段三方面系统强化。


8.1 跨平台稳定性策略
项目建议
Request 参数仅使用 CameraCharacteristics.getAvailableCaptureRequestKeys() 中存在的 Key
流组合尽量控制流 ≤ 3 路(Preview + JPEG + YUV),避免高并发流失败
分辨率选择YUV 推荐 ≤ 1920×1080,Preview 推荐 ≤ 720p,兼顾性能与稳定性
模板选型ZSL 拍照建议使用 TEMPLATE_ZERO_SHUTTER_LAG,若平台不支持应回退至 STILL_CAPTURE
Session 创建避免多次反复绑定同一个 Surface,引发 HAL 重建流失败

8.2 错误容错机制设计
  1. HAL 请求失败处理:
    • 捕获 onCaptureFailed() 中的 CaptureFailure.REASON_ERROR
    • 自动重试拍照请求(次数 ≤ 3),配合对焦/曝光重置
  2. 流配置失败处理:
    • 捕获 onConfigureFailed() 回调
    • 检查 Surface 对应的尺寸、格式是否不被支持
    • 动态切换回 fallback 尺寸(如降级至 1280×720)
  3. AF/AE 长时间不收敛:
    • 设置 metadata 超时监控(如 1s 内未 CONVERGED,取消或改为手动)
    • 引导 UI 层提示用户重新构图
  4. ImageReader 超时 / ImageProxy 为空:
    • 设置图像帧接收超时机制(如 500ms)
    • 若回调未触发 → 释放资源并重新构建 UseCase

8.3 Trace 调试入口推荐(ATRACE × systrace)

建议在以下函数添加自定义 ATRACE 点:

函数位置ATRACE 标签建议
processCaptureRequest()HAL::processCaptureRequest
jpeg_encode()HAL::jpeg_encode
onImageAvailable()Framework::onImageAvailable
CameraCaptureSession.capture()Camera2::capture()
CameraX.takePicture()CameraX::ImageCapture::takePicture

抓取方式:

adb shell atrace -z -b 8192 -t 10 camera hal gfx sched view > trace.html

或使用 perfetto 配置追踪完整帧路径。


8.4 多平台适配实战建议
平台特性工程应对策略
高通(Qcom)UBWC 格式默认开启、ZSL 支持完整确保使用标准模板;抓拍场景建议开启 ZSL
MTKAE/AF 收敛较慢,部分机型 AE_STATE 抖动严重增加拍照前稳定延迟(如 waitUntil AF+AE converged)
海思JPEG 编码为异步流程,拍照回调滞后延迟判断超时,谨慎处理 ImageReader buffer 生命周期

原文:https://zhxin.blog.csdn.net/article/details/149726165