Chapter 163: Android Deep Path Camera Request
一次 Android 拍照请求看起来从应用里的一次 capture() 调用开始,系统内部实际经过应用对象、framework 代理、Binder IPC、CameraService、HAL session、kernel driver、ISP、sensor 和共享 buffer。读完本章后,读者应能追踪一次 Camera2 拍照请求经过哪些层级,判断失败发生在权限、资源仲裁、stream 配置、HAL 执行、driver 或硬件阶段。
本章的贯穿材料是一次典型 Camera2 行为:应用已经显示预览画面,用户点击拍照按钮,应用向当前 CameraCaptureSession 提交一个 JPEG still capture request,同时保持 preview repeating request。这个材料覆盖相机路径的关键对象:Surface 表示输出目标,CaptureRequest 表示一次采集意图,CameraCaptureSession 表示已经配置好的流组合,CameraService 表示系统资源所有者,HAL session 表示厂商相机管线入口,driver 和 ISP 表示硬件执行边界。
公开资料边界需要先固定。Android Developers 的 Camera2 package summary 描述了 CameraDevice、CameraCaptureSession、CaptureRequest、Surface、TotalCaptureResult 的应用层关系;AOSP 的 Camera 架构文档 描述了 app framework、AIDL/Binder、native framework、CameraService、HAL 的分层关系;AOSP 的 Camera HAL 文档 说明 HAL 位于 framework 与 driver/hardware 之间。本文按 Android 6.0 之后运行时相机权限、Android 12 之后相机隐私指示器和开关、Android 8.0 之后 Treble 时代 HAL 边界来讲,具体设备上的 HAL 绑定形式、vendor 实现和算法管线会随 Android 版本、SoC 和 OEM 调整变化。
理解这条路径的关键结论是:应用提交的是受约束的“请求描述”,系统服务持有设备所有权,HAL 将请求转换成厂商管线工作,driver 和硬件产生 frame 与 metadata,最后结果沿回调和 buffer 返回应用。权限、AppOps、SELinux、资源占用、stream combination、buffer 可用性、硬件状态都可能改变最终结果。
163.1 Camera Request 的跨层路径总览
一次拍照请求的主路径可以先压缩成一句话:应用把 capture metadata 和输出 Surface 交给 framework,framework 通过 Binder 调到 CameraService,CameraService 在通过权限和资源检查后把请求送入 HAL session,HAL 驱动 sensor、ISP 和 buffer 队列,最终返回 CaptureResult 与图像 buffer。
这条路径里有两个对象贯穿全程。第一个对象是 request,它在应用层表现为 CaptureRequest,在 native service 和 HAL 边界会被转换成平台内部 metadata 结构和 HAL request。第二个对象是 output target,它在应用层是 Surface,在 native 层对应可跨进程传递的 buffer producer/consumer 关系,在 HAL 和 driver 层变成可由 ISP/DMA 写入的图像 buffer。
下面这张图只画一次 still capture 的主干,不展开 autofocus、auto exposure、multi-frame HDR、vendor extension、offline processing 等派生路径。图中的 preview repeating request 和 still capture request 可以共用同一个 session,still capture 通常会抢占下一帧或若干帧的管线调度位置。
从应用视角看,capture() 返回只表示请求已经提交给 session,并不等于 sensor 已曝光,也不等于 JPEG 已经写入 ImageReader。Camera2 API 的异步设计把“请求被接受”“3A 状态变化”“metadata 回调”“图像 buffer 到达”拆成不同事件,这使系统可以在高帧率 preview、still capture、video recording 和多摄管线之间安排硬件资源。
这条路径的第一组失败发生在请求进入硬件之前。应用缺少 CAMERA runtime permission、相机全局开关关闭、AppOps 拒绝、设备被更高优先级 client 占用、session 的 stream 组合超出硬件能力、目标 Surface 已释放,都会让请求停在 framework 或 CameraService。第二组失败发生在硬件执行期间,例如 HAL 返回 error、driver 超时、sensor 断开、buffer 不可用、ISP 管线失败。两组失败的排查入口不同:前者看权限和服务状态,后者看 HAL/device 状态与 capture callback。
163.2 App Layer:Camera2 API、CaptureRequest、Surface
应用层的核心任务是把“我要拍一张照片”表达成三个可检查对象:选中的 camera id,已经配置好的输出 Surface 集合,以及一次 CaptureRequest。应用不会直接控制 sensor 寄存器,也不会直接分配 ISP 管线;它只能在 framework 暴露的能力表面内声明目标格式、尺寸、控制项和回调。
Surface 是 Camera2 路径里的输出端点。预览常见目标是 SurfaceView、TextureView 或渲染管线提供的 surface,拍照常见目标是 ImageReader 的 surface,录像目标来自 MediaRecorder 或 encoder。应用创建 session 时必须先给出这些 surface,系统据此判断 stream combination 是否可支持,HAL 据此准备对应 buffer 队列和图像格式。
CaptureRequest 是一次采集的控制包。它包含输出 targets,也包含曝光、对焦、闪光灯、JPEG orientation、噪声抑制、色彩、crop region 等 metadata key。Camera2 文档把 CaptureRequest 定义为一次图像采集所需设置与输出的不可变包;应用使用 builder 设置字段,提交后 request 进入 session 队列,后续回调用 result 说明最终采用的设置。
下面的 Kotlin 片段只保留 still capture 的关键结构。它展示应用层能表达什么,也展示应用层交给系统的对象边界。
// Simplified Camera2 still capture path.
val imageReader = ImageReader.newInstance(width, height, ImageFormat.JPEG, 2)
val previewSurface = previewView.holder.surface
val jpegSurface = imageReader.surface
cameraDevice.createCaptureSession(
listOf(previewSurface, jpegSurface),
sessionCallback,
cameraHandler
)
val stillRequest = cameraDevice
.createCaptureRequest(CameraDevice.TEMPLATE_STILL_CAPTURE)
.apply {
addTarget(jpegSurface)
set(CaptureRequest.CONTROL_AF_MODE, CaptureRequest.CONTROL_AF_MODE_CONTINUOUS_PICTURE)
set(CaptureRequest.JPEG_ORIENTATION, jpegOrientation)
}
.build()
captureSession.capture(stillRequest, captureCallback, cameraHandler)
这段代码没有展示权限请求、相机打开、preview repeating request、生命周期释放和错误分支,因为本节只定位 request 形态。真正的应用代码需要把 ImageReader 生命周期、session 生命周期、Activity/Fragment 生命周期对齐:页面暂停时释放 session 或 device,surface 销毁时停止提交 request,收到 CameraAccessException 或 onDisconnected() 时把 UI 切到可恢复状态。
从系统路径角度看,应用层提供的是意图和 buffer 入口。它能决定“把本帧写到哪个 surface”“本次希望使用哪些控制参数”“结果通过哪个 callback 返回”。这些参数最终会经过系统和硬件能力裁剪后执行。最终 result 可能经过设备能力裁剪、3A 算法调整、HAL 合法性检查和硬件时序约束。
163.3 Framework Layer:CameraManager、CameraDevice、Session
Framework 层把应用对象转换成可被系统服务理解的相机会话状态。CameraManager 负责枚举与打开设备,CameraDevice 表示已经打开的单个 camera,CameraCaptureSession 表示一组 stream 已经配置完成并可接收 request。应用看到的是 Java/Kotlin API,系统内部同时维护 native 对象、Binder proxy、surface handle 和 callback 分发。
打开设备时,CameraManager.openCamera() 会把 package、UID、attribution、callback executor 或 handler 等上下文带入请求。这个阶段要建立“谁在使用相机”的身份,因为 CameraService 后续要据此做 permission、AppOps、隐私指示器和资源优先级判断。打开成功后,应用拿到 CameraDevice,此时设备还没有可用输出管线,必须配置 session 才能提交 request。
Session 配置是 request 能进入 HAL 的前置条件。应用给出一组输出 surface,framework 会把 surface 的尺寸、格式、动态范围、旋转、usage 等信息整理成 stream configuration。CameraService 和 HAL 会在这个阶段判断组合是否可支持。例如同一个设备可能支持一路 preview 加一路 JPEG,也可能在高分辨率、RAW、深度、视频录制、高帧率模式下收缩可用组合。
重复请求和单次捕获在 framework 层有不同队列语义。setRepeatingRequest() 让 preview 持续生产帧,capture() 插入一次 still request。Camera2 文档说明 repeating request 的优先级低于单次 capture;因此用户点击拍照时,still capture 可以在 repeating preview 之间获得执行机会。这个行为解释了为什么预览不断流,同时仍能触发一次高质量 JPEG 输出。
Result 回调也在 framework 层完成对象还原。HAL 返回 metadata 后,CameraService 将结果送回 framework,framework 再回调 CameraCaptureSession.CaptureCallback。图像 buffer 则沿 Surface 对应的 buffer 队列到达 ImageReader.OnImageAvailableListener。metadata 和 image buffer 可能存在时间差,应用需要用 frame number、timestamp 或自身请求序列建立对应关系。
Framework 层的稳定判断顺序是:先确认 camera id 和 characteristics,再确认 session stream 配置,再确认 repeating request 是否已经运行,最后确认 still request 的 callback 与 image buffer 是否到达。这个顺序能把“打不开相机”“能打开但 session 配置失败”“能预览但拍照失败”“能拍照但拿不到图片”拆到不同边界。
163.4 Binder Layer:Camera Service 远程调用
Binder 层承担跨进程传递和身份保留。应用进程调用的是 framework 对象,真正持有相机设备状态的是 native CameraService。Binder 让 framework proxy 调用 system service 方法,同时保留 caller UID、PID、package、attribution tag 和 callback binder,使服务能知道请求来自哪个应用,并能把断开、错误和结果回调送回原始 client。
AOSP 相机架构文档把 CameraService 相关 Binder 接口放在相机 framework 与 service 之间,例如服务入口、已打开设备接口和回调接口。这个设计让应用进程不直接链接 vendor HAL,也不直接进入 driver。应用只拿到一个远程设备句柄;这个句柄背后由 CameraService 维护 client 对象、device 状态、stream 配置、request 队列和死亡通知。
Binder 传递 Surface 时交付的是可跨进程引用的 native handle 和 buffer queue 关系,Java 对象本体仍停留在应用进程语境。CameraService 需要能把输出目标交给 HAL,使 HAL 最终可以拿到待写入的 buffer。这个过程让图像数据走共享 buffer 和 fence 路径,控制消息走 Binder 路径。控制流和数据流分离,是 Camera2 能同时保持高吞吐图像输出和清晰权限边界的原因。
Binder death 是相机路径的故障隔离机制。应用进程退出、崩溃或被系统回收时,CameraService 可以通过 binder death 释放对应 client,占用的 camera device、stream 和 buffer 引用会进入清理流程。CameraService 或 cameraserver 进程异常时,framework 会收到 disconnect 或 error callback,应用需要关闭当前对象并重建相机路径。
Binder 层的排查结论很直接:如果应用已经有 permission,但 openCamera() 返回断开或访问异常,问题可能已经进入 service arbitration 或 service 可用性;如果 session 建立后回调顺序异常,要区分 callback binder 断开、surface 被释放、device 断开和 HAL error。Binder 的主要责任是跨进程调用、身份传递、句柄传递和生命周期隔离,图像处理由 HAL、driver、ISP 和编码路径承担。
163.5 System Service Layer:CameraService、Client、Resource Arbitration
CameraService 是 Android 相机路径里的系统所有者。它负责管理可用 camera 列表、打开和关闭设备、创建 client、维护设备占用状态、执行权限与 AppOps 检查、协调并发 client、向 HAL 发起配置和 request、向应用回调状态。应用能否使用相机,最终要通过这个服务的判断。
资源仲裁是 CameraService 的核心工作之一。手机上相机常常被多个入口竞争:系统相机、第三方扫码、视频会议、浏览器网页拍照、后台服务、锁屏或系统 UI。CameraService 需要依据 UID、进程状态、前后台、系统 client、已连接设备和设备支持能力决定谁能打开、谁被拒绝、谁被断开。被抢占或断开的应用会收到 onDisconnected() 或错误回调,用户看到的是预览停止、按钮不可用或相机被占用提示。
权限检查在服务层具有实际执行意义。应用在 UI 层请求 CAMERA runtime permission 只是取得授权状态,CameraService 仍要在打开设备和开始使用时检查调用者身份、权限、AppOps 和传感器隐私状态。Android 12 之后的相机全局开关和状态栏指示器也让“正在使用相机”成为用户可见状态;服务层和系统 UI 需要围绕相机 active 状态更新可见提示。
Client 对象把一个应用连接抽象成服务内部资源实体。一个 client 记录 camera id、调用者身份、回调、device session、stream 配置、当前 request 状态和错误状态。这个抽象使 CameraService 可以在应用侧对象已经消失、Binder 已经死亡或 HAL 发生错误时统一释放资源,防止 camera device 长时间被失效连接占用。
错误恢复同样在 CameraService 聚合。HAL 返回 device error、request error、buffer error,driver 超时,provider 断开,sensor 隐私状态改变,都会被服务层转换成 Camera2 callback 或可恢复的断开事件。应用排查时要看错误发生前的阶段:打开阶段失败通常指向权限、占用或服务不可用;session 配置失败通常指向 stream combination 或 surface;capture 期间失败通常指向 HAL、buffer 或硬件执行。
系统服务层的判断顺序是:先看调用者是否有使用资格,再看设备是否可被当前 client 占用,再看 stream 配置是否进入 HAL,再看 request 是否被 HAL 接受,再看 result 和 buffer 是否返回。这个顺序把“安全资格”“资源所有权”“能力配置”“硬件执行”“返回交付”分成五个可定位边界。
163.6 HAL Layer:Camera Provider、Camera Device、Stream Configuration
HAL 层把 Android 标准相机接口连接到厂商相机管线。AOSP 文档中典型 binderized HAL 需要 provider、device、session 等接口角色:provider 枚举设备和状态,device 表示某个 camera,session 表示打开后的活动控制通道。具体接口形式会随平台版本使用 HIDL 或 AIDL 等绑定机制,稳定职责是相同的:向 CameraService 提供设备列表、能力描述、stream 配置、request 执行和 result 返回。
Camera provider 首先回答“系统上有哪些 camera”。它把物理摄像头、逻辑多摄、前后摄、外接摄像头和可用状态报告给 CameraService。对于逻辑多摄,provider 可能把多个物理 sensor 组合成一个逻辑 camera id,并通过 metadata 描述焦段、同步、能力和物理 camera id。应用看到的 camera id 已经是系统和 vendor 协商后的能力表面。
Stream configuration 是 HAL 层的重要门槛。CameraService 把 framework 层的 surface 需求转换成 stream 列表,HAL 判断尺寸、格式、usage、动态范围、数据空间、旋转、stall 行为、buffer 数量和组合约束。通过配置后,HAL 准备对应内部管线;失败时,应用看到 session 配置失败或 CameraAccessException。这说明很多“代码看起来正确”的问题实际是 stream 组合超出设备 profile。
Capture request 进入 HAL session 后,会被转成 vendor 管线任务。一个 request 通常包含 frame number、settings metadata、output buffer 列表和可选 input buffer。HAL 需要安排 sensor 曝光、ISP 处理、3A 状态、JPEG 编码、buffer fence、timestamp 和 result metadata。仍在运行的 repeating preview request 与插入的 still capture request 共享硬件管线,因此 HAL 必须处理队列顺序、延迟、stall 和 buffer 背压。
HAL 也是安全边界。AOSP Camera 文档明确把 CameraService 与 HAL 的边界视为安全边界,要求 HAL 校验来自 CameraService 的参数。原因是 HAL 拥有与 CameraService 不同的资源访问能力,可能接近 kernel driver、vendor daemon、firmware 和硬件寄存器。HAL 对 buffer 长度、stream 参数、metadata 合法性和硬件命令做校验,能减少越界访问和权限扩大风险。
HAL 层返回的结果分两类。第一类是 metadata result,例如曝光时间、sensor timestamp、AF/AE/AWB 状态、实际 crop、噪声模式、闪光灯状态。第二类是 buffer status,例如某个 output buffer 填充完成、失败或被取消。应用最终收到的 TotalCaptureResult 和 ImageReader image 来自这两条返回链,二者的到达顺序可以有差异。
163.7 Kernel / Hardware Layer:Driver、ISP、Sensor、Buffer
Kernel 和硬件层把 request 转换为真实的光电采集和图像数据搬运。Sensor 负责曝光和读出,镜头执行对焦或防抖动作,ISP 处理 raw data、demosaic、降噪、色彩、HDR、tone mapping,JPEG 或 HEIF 编码单元产生最终图片,DMA 和 IOMMU 让图像数据写入共享 buffer。Driver 和 vendor firmware 把这些硬件动作包装成 HAL 可调用的控制队列。
相机 driver 的职责通常包括 sensor 控制、MIPI CSI 接收、ISP 子设备配置、clock 和 power domain、interrupt、buffer queue、timestamp 和错误上报。Android framework 不直接面对这些对象;它只看到 HAL 抽象后的 metadata 和 buffer 状态。这个分层使不同 SoC、不同 sensor、不同 ISP 算法可以共用同一 Camera2 API 表面。
Buffer 是硬件层和应用层连接最紧的对象。应用创建 ImageReader 后,系统为它准备可被 producer 写入的 buffer。HAL 从对应队列取得空闲 buffer,把它交给 ISP 或编码路径,硬件完成后通过 fence 和状态把 buffer 归还给上层。应用调用 Image.close() 释放 buffer,释放不及时会导致可用 buffer 数减少,进而造成 preview 卡顿、still capture 延迟或 request 队列背压。
Timestamp 是跨层对齐的关键证据。Sensor timestamp 表示 frame 采集时刻,metadata result 带有对应 frame number 和 timestamp,image buffer 也有 timestamp。应用如果需要把预览帧、拍照结果、传感器数据或 UI 事件对齐,应使用这些时间戳;callback 到达时间只能说明上层收到事件的时间。
硬件层失败常表现为延迟、黑帧、花屏、buffer error、device error、HAL timeout 或 session 断开。它们和权限错误的用户表现可能相似,例如 UI 都显示“拍照失败”,但责任边界不同。权限和资源失败通常在 open/session/capture 提交前暴露;硬件失败通常在 request 已接受后,通过 onCaptureFailed()、device error、provider death 或图像 buffer 状态暴露。
对工程排查而言,Kernel / Hardware 层的可迁移判断是:先确认上层 request 已经被接受,再看是否有 result metadata,再看是否有 image buffer,再根据 frame number 和 timestamp 判断是哪一帧失败。这个顺序可以把“没有提交成功”“提交成功但 HAL 未返回 result”“result 返回但 buffer 失败”“buffer 返回但画质异常”分开。
163.8 Permission、AppOps、SELinux、Privacy Indicator 的检查点
相机请求路径的安全检查分散在多个层级。Manifest 与 runtime permission 决定应用是否取得用户授权,AppOps 记录和控制敏感能力使用,CameraService 在服务边界执行调用者检查,SELinux 限制进程访问 service、device node 和 vendor 资源,privacy indicator 把活跃访问呈现给用户。它们共同把相机硬件包装成可授权、可审计、可撤销的系统能力。
Runtime permission 的入口在应用体验中最明显。Android Developers 的 runtime permissions 文档 说明 Android 6.0 之后危险权限需要在运行时请求。相机属于危险权限范围;用户拒绝或撤销后,应用应降级相机功能,例如隐藏拍照入口、显示导入图片入口或提示重新授权。这个授权状态只解决应用资格的一部分,后续服务检查仍会执行。
AppOps 可以理解为敏感操作的运行期开关和审计层。即使 manifest 与 runtime permission 状态看起来满足要求,CameraService 仍会按调用者身份检查对应 operation。用户、企业策略、系统传感器开关、兼容性规则或平台策略可能改变 operation 结果。对应用而言,正确处理方式是把访问失败视为可恢复状态,释放相机对象并更新 UI。
SELinux 位于进程和内核资源边界。AOSP 的 SELinux 文档 说明 Android 使用 SELinux 对所有进程执行强制访问控制,并在 enforcing 模式下阻止未被策略允许的动作。对相机路径而言,普通 app 缺少直接访问 camera device node 的策略资格;CameraService、vendor camera provider、HAL 进程和 driver 节点之间也受各自 domain 与 policy 约束。这样即使某一层发生漏洞,攻击面仍受进程域和资源标签限制。
Privacy indicator 和传感器开关把系统内部访问状态映射到用户可见体验。Android 12 之后,支持设备在应用访问 camera 或 microphone 时会显示状态栏图标,并提供相机和麦克风全局开关。Android Developers 的 Android 12 behavior changes 对相机/麦克风 toggles 与 indicators 做了版本说明。对拍照请求来说,这意味着 CameraService 需要把 client active 状态同步给系统隐私界面,用户也可以通过全局开关切断后续访问。
把检查点放回贯穿材料,可以得到一条稳定路径:应用点击拍照前先具备 runtime permission;打开 camera 时 CameraService 校验 UID、package、AppOps、sensor privacy 和资源状态;跨进程调用受 Binder 身份和服务接口约束;HAL 和 vendor 进程受 SELinux 与 HAL 参数校验约束;硬件激活后系统 UI 显示相机使用状态;用户撤销权限或关闭相机开关后,后续 open 或 active request 会失败或断开。
这组检查的排查顺序应从用户可见状态开始:权限是否授予,相机全局开关是否开启,是否有其他应用占用,相机 session 是否配置成功,capture callback 是否返回错误,系统是否报告 device/service 断开。把这些问题按层级排列,比直接猜测“相机坏了”更可靠。
最小自检任务
你在一个 Camera2 应用里实现了预览和拍照。预览已经正常显示,用户点击拍照后没有得到 JPEG 图片,UI 收到一次 capture failure。请写出从应用层到硬件层的排查路径,并说明每一步对应的责任主体、资源边界、策略判断和用户可见结果。
答案要点
第一步看应用层对象。确认 still CaptureRequest 的 target 是否指向 ImageReader.surface,ImageReader 是否仍存活,listener 是否设置,应用是否及时关闭旧 Image。如果 buffer 没有释放,责任边界在应用持有的输出队列,用户看到的是拍照延迟或没有新图片。
第二步看 framework session。确认当前 CameraCaptureSession 是否已经配置成功,preview repeating request 是否运行,still capture 是否提交到同一个有效 session。session 关闭、surface 销毁或生命周期错位会让 request 在 framework 边界失败,用户看到的是按钮可点但回调报错。
第三步看 CameraService 仲裁。确认应用仍有 CAMERA permission,相机全局开关开启,AppOps 允许,当前设备没有被更高优先级 client 抢占。这个阶段的责任主体是 CameraService 和系统权限策略,用户看到的是权限提示、相机被占用、预览断开或功能降级。
第四步看 HAL 与 stream 配置。确认 preview surface 加 JPEG surface 的尺寸、格式和动态范围组合处在设备能力范围内。配置组合超出能力时,服务可以拒绝 session 或 HAL 可以返回配置错误,用户看到的是预览建立失败或拍照入口不可用。
第五步看 request 执行与硬件返回。request 已被接受后,如果没有 TotalCaptureResult 或 buffer 状态失败,问题进入 HAL、driver、ISP、sensor 或 buffer fence 路径。此时应根据 frame number、timestamp、capture failure reason 和 device error 区分 HAL 执行失败、buffer 不可用、sensor/ISP 异常和设备断开。
核心结论是:预览正常只证明 preview stream 和 repeating request 成立,JPEG still capture 还需要单独验证 target、session、HAL stream 和 output buffer。拍照失败要沿 CaptureRequest target → session state → CameraService checks → HAL stream/request → result and buffer 顺序定位,先分清请求有没有进入硬件,再判断硬件有没有交回 metadata 和图像 buffer。
本章知识点总结
- 请求主线:一次 Camera2 拍照请求从
CaptureRequest和Surface开始,经 framework、Binder、CameraService、HAL、driver、ISP 和 sensor 返回 result 与 buffer。 - 对象边界:应用提交的是采集意图和输出目标,设备所有权、stream 能力和硬件执行由系统服务与 HAL 控制。
- Surface 角色:
Surface是图像输出端点,预览、拍照和录像通过不同 surface 进入同一个 session 配置判断。 - Request 语义:
CaptureRequest描述一帧或一组帧的控制参数和 targets,最终执行参数以返回的 result 为准。 - Session 前提:
CameraCaptureSession表示 stream 组合已经配置完成,capture request 只有在有效 session 内才具备执行路径。 - Binder 作用:Binder 负责跨进程调用、身份传递、handle 传递和死亡通知,图像数据主要沿共享 buffer 路径移动。
- 服务所有权:CameraService 管理设备列表、client、权限、AppOps、资源仲裁、HAL 调用和错误回调。
- HAL 职责:Camera HAL 将 Android 标准接口转换成厂商相机管线任务,并返回 metadata 与 buffer status。
- 硬件执行:Sensor、ISP、driver、DMA、fence 和 buffer queue 共同完成曝光、处理、编码和图像交付。
- 权限检查:Runtime permission、AppOps、sensor privacy、CameraService 检查和 SELinux 共同决定相机能力能否被使用。
- 隐私提示:Android 12 之后的相机指示器和全局开关把相机 active 状态变成用户可见控制面。
- 排查顺序:相机问题应按应用 target、session、服务检查、HAL 配置、request 执行、result 和 buffer 交付逐层定位。