引言:谁来仲裁相机资源争夺战?
想象这样一个场景:你正在用第三方相机 APP 录制 4K 视频,这时微信来了一个视频通话请求。你接了通话——这时候,系统需要把相机从录像 APP "抢"过来交给微信。
这场"争夺战"怎么判定胜负?凭什么微信就能赢?被抢走的录像 APP 怎么感知到这件事?抢走后如何安全地交接给新的使用者?
这一切,都是 CameraService 负责的事情。
CameraService 是 Android 相机体系的核心服务,运行在独立的 cameraserver 进程中,扮演着"相机资源大管家"的角色。它:
- 管理所有物理相机设备的状态
- 仲裁多应用竞争相机的冲突
- 连接 Java 层 Camera2 API 与底层 HAL Provider
- 控制相机权限和隐私指示器
- 应对温度过高时的 Thermal 限流
本文是 Android 15 视频子系统系列第 2 篇,深入剖析 CameraService 的服务架构和资源管理机制。
本文内容:
- CameraService 整体架构与模块组成
- CameraProviderManager 与 HAL Provider 管理
- 多应用相机资源仲裁机制(核心!)
- 相机权限与隐私保护
- 性能、功耗与 Thermal 管理
- 调试工具完全指南
一、CameraService 整体架构
1.1 进程与启动
CameraService 运行在 cameraserver 独立进程中,在系统启动时由 init 进程拉起:
# frameworks/av/camera/cameraserver/cameraserver.rc
service cameraserver /system/bin/cameraserver
class main
user cameraserver
group audio camera input drmrpc
ioscheduler rt 4
writepid /dev/cpuset/camera-daemon/tasks /dev/stune/top-app/tasks
// frameworks/av/camera/cameraserver/main_cameraserver.cpp
int main(int argc __unused, char** argv __unused)
{
signal(SIGPIPE, SIG_IGN);
// 设置进程优先级
hardware::configureRpcThreadpool(5, false);
sp<ProcessState> proc(ProcessState::self());
sp<IServiceManager> sm = defaultServiceManager();
// 注册 CameraService 到 ServiceManager
CameraService::instantiate();
// 注册 Android Sensors
SensorService::instantiate();
ProcessState::self()->startThreadPool();
IPCThreadState::self()->joinThreadPool();
}
注意 cameraserver 进程以 cameraserver 用户身份运行(非 root),并且加入了 camera 组,这是 SELinux 权限控制的一部分。
1.2 四大核心模块
CameraService 内部由四个核心模块组成,各司其职:
| 模块 | 对应类 | 核心职责 |
|---|---|---|
| Binder 服务端 | CameraDeviceClient | 接收 App 的 Camera2 API 调用,通过 Binder 暴露给 Java 层 |
| Provider 管理器 | CameraProviderManager | 管理所有 Camera HAL Provider,枚举相机设备,查询设备能力 |
| 客户端管理器 | ClientManager | 跟踪所有已连接的相机客户端,实施优先级仲裁和抢占 |
| 权限管理器 | CameraService::PermissionHandler | 校验 CAMERA 权限,触发隐私指示器,实施 Thermal 限流 |
frameworks/av/services/camera/libcameraservice/
├── CameraService.cpp # 主服务入口,多应用仲裁
├── CameraService.h
├── common/
│ └── CameraProviderManager.cpp # Provider 管理
├── api2/
│ └── CameraDeviceClient.cpp # Camera2 API 服务端
├── utils/
│ └── ClientManager.cpp # 客户端优先级管理
└── device3/
└── Camera3Device.cpp # Camera3 设备实现
二、CameraProviderManager:HAL 的"中间人"
2.1 Provider 是什么?
Camera HAL3 的架构中,ICameraProvider 是芯片厂商(高通/MTK/三星)向 Android 框架暴露相机能力的接口。一台设备上可能有多个 Provider:
| Provider 类型 | 类名 | 说明 |
|---|---|---|
| 内置相机 Provider | InternalCameraProvider | 管理前置/后置摄像头,最常见 |
| 外接相机 Provider | ExternalCameraProvider | 管理 USB 外接摄像头,支持热插拔 |
| 旧版兼容 Provider | LegacyCameraProvider | 为 HAL1/HAL3 以下设备提供兼容层 |
// frameworks/av/services/camera/libcameraservice/common/CameraProviderManager.cpp
status_t CameraProviderManager::initialize(wp<StatusListener> listener,
ServiceInteractionProxy* proxy) {
// 通过 AIDL/HIDL 发现所有已注册的 CameraProvider
auto manager = hardware::camera::provider::V2_4::ICameraProvider::getService("legacy/0");
if (manager != nullptr) {
addProviderLocked("legacy/0", manager);
}
// 监听新 Provider 的动态注册(USB 相机热插拔时触发)
// ...
return OK;
}
2.2 相机设备枚举
当 App 调用 CameraManager.getCameraIdList() 时,最终调用的是:
// frameworks/av/services/camera/libcameraservice/CameraService.cpp
Status CameraService::getCameraIds(std::vector<std::string>* ids) {
Mutex::Autolock l(mServiceLock);
// 从 CameraProviderManager 获取所有可用相机 ID
auto providerManager = mCameraProviderManager;
providerManager->getCameraDeviceIds(ids);
// 过滤掉当前进程无权访问的相机(权限检查)
auto caller = CameraThreadState::getCallingPid();
// ...
return Status::ok();
}
2.3 相机特性查询
CameraCharacteristics 数据从 HAL Provider 一路流上来:
// 查询流程:Java 层 → CameraService → CameraProviderManager → HAL Provider
Status CameraService::getCameraCharacteristics(const std::string &cameraId,
int targetSdkVersion, CameraMetadata *characteristics) {
// 1. 通过 ProviderManager 找到对应的 Provider
sp<CameraProviderManager::ProviderInfo::DeviceInfo> deviceInfo;
mCameraProviderManager->getCameraCharacteristics(cameraId, characteristics);
// 2. 追加 CameraService 层的补充特性(如 HAL 支持的最大连接数)
// ...
return Status::ok();
}
HAL 层的特性数据(如传感器尺寸、支持的分辨率、3A 能力)以 CameraMetadata(一种键值对结构)的形式从 HAL 传递到 Java 层。
2.4 外接 USB 相机的热插拔
外接相机(如 USB 摄像头)支持热插拔,ExternalCameraProvider 通过监听 udev 事件来感知:
// frameworks/av/services/camera/libcameraservice/device3/ExternalCameraUtils.cpp
// 当检测到新的 USB 视频设备(/dev/videoN)时:
void ExternalCameraProviderImpl_2_4::deviceAdded(const char* devName) {
// 检查设备是否是有效的相机
if (!isUsbCamera(devName)) return;
// 生成相机 ID(如 "external/0")
std::string cameraId = generateCameraId(devName);
// 通知 CameraProviderManager 有新相机接入
mCallbacks->cameraDeviceStatusChange(cameraId,
CameraDeviceStatus::PRESENT);
// App 层的 CameraManager.AvailabilityCallback.onCameraAvailable() 被触发
}
三、多应用相机资源仲裁(核心机制)
这是 CameraService 最复杂、也最重要的功能。多个 App 同时竞争相机时,谁赢谁输?
3.1 客户端优先级体系
Android 定义了一套相机客户端优先级,数值越小优先级越高:
// frameworks/av/services/camera/libcameraservice/utils/ClientManager.h
enum class Priority : int32_t {
// 优先级数值越小 = 越高
FOREGROUND_APP = 0, // 前台应用(用户可见)
TOP_ACTIVITY = 1, // 顶层 Activity(最高优先级)
SYSTEM_NRT = 2, // 系统非实时服务
BACKGROUND = 3, // 后台应用
// ... 更多级别
};
优先级的实际值来自 ActivityManagerService(AMS),CameraService 通过查询 AMS 的进程状态来确定优先级:
// CameraService 查询进程状态
int32_t CameraService::getCameraPriorityFromProcState(int procState) {
// PROCESS_STATE_TOP = 2(顶层前台 App)→ 最高优先级
// PROCESS_STATE_IMPORTANT_FOREGROUND = 5(前台服务)→ 较高优先级
// PROCESS_STATE_CACHED_EMPTY = 16(缓存进程)→ 最低优先级
return procState; // 直接用 procState 作为相机优先级
}
3.2 抢占判定逻辑
当新的 App(App A)请求打开相机,而相机已经被另一个 App(App B)占用时:
// frameworks/av/services/camera/libcameraservice/CameraService.cpp
Status CameraService::connectHelper(const sp<CALLBACK>& cameraCb,
const String8& cameraId,
int clientPid,
uid_t clientUid,
int servicePid,
/*out*/ sp<CLIENT>& device) {
// 1. 检查权限
if (!hasPermissionsForCamera(clientPid, clientUid)) {
return STATUS_ERROR(ERROR_PERMISSION_DENIED, "No CAMERA permission");
}
Mutex::Autolock lock(mServiceLock);
// 2. 查找已连接到此相机的客户端
sp<BasicClient> clientToDisconnect;
{
auto clientDescriptor = mActiveClientManager.get(cameraId);
if (clientDescriptor != nullptr) {
clientToDisconnect = clientDescriptor->getValue();
}
}
// 3. 如果有冲突,检查优先级
if (clientToDisconnect != nullptr) {
int32_t newClientPriority = getCameraPriorityFromProcState(
getProStateFromPid(clientPid));
int32_t oldClientPriority = clientToDisconnect->getCameraClientPriority();
if (newClientPriority >= oldClientPriority) {
// 新客户端优先级不更高,拒绝!
ALOGW("Higher-priority app already using camera %s, rejecting",
cameraId.c_str());
return STATUS_ERROR_FMT(ERROR_CAMERA_IN_USE,
"Higher priority app is using camera %s",
cameraId.c_str());
}
// 新客户端优先级更高 → 强制断开旧客户端
ALOGI("Evicting client for camera %s due to higher priority app",
cameraId.c_str());
// 触发 App B 的 onDisconnected() 回调
clientToDisconnect->disconnect();
}
// 4. 创建新的相机客户端并注册
// ...
return Status::ok();
}
💡 关键理解:被抢占(evict)的 App 会收到
CameraDevice.StateCallback.onDisconnected()回调,这是 App 感知"相机被抢走"的唯一方式。一个健壮的相机 APP 必须正确处理这个回调——释放所有相机资源,并在需要时显示提示("相机被其他 APP 占用")。
3.3 优先级实际案例
以下是常见场景的优先级判定结果:
| 场景 | App A(新请求) | App B(当前占用) | 结果 |
|---|---|---|---|
| 视频通话抢相机 APP | 前台前景 App(优先级高) | 后台 App(优先级低) | App A 胜,App B 被断开 |
| 后台 App 抢前台相机 | 后台 App(优先级低) | 前台 App(优先级高) | App A 被拒绝,返回 ERROR_CAMERA_IN_USE |
| 系统服务 vs 用户 App | 系统 NRT(中等优先级) | 普通用户 App | 取决于具体优先级数值 |
| 两个前台 App | 前台 App(相同优先级) | 前台 App(相同优先级) | 先到先得,后来者被拒绝 |
3.4 多相机并发(Android 11+)
在 Android 11 之前,同一时间只能有一个 App 使用相机(即使是不同摄像头)。Android 11 引入了多相机并发(Concurrent Camera),允许特定的相机组合同时开启:
// App 开发者:查询哪些相机可以并发使用
Set<Set<String>> concurrentIds = cameraManager.getConcurrentCameraIds();
// 例如:concurrentIds = {{"0", "1"}} 表示前后置可同时开
// 打开并发相机(需要使用 openCameraInSharedMode())
// Android 15 支持 SHARED_MODE 允许多 App 同时读取同一相机流(读取优先级,适合 AR 场景)
在 CameraService 侧,并发相机支持通过 CameraProviderManager 查询 HAL Provider 是否声明了并发支持:
// 查询支持并发的相机组合
status_t CameraProviderManager::getConcurrentCameraIds(
std::vector<std::vector<CameraIdAndStreamCombination>>* concurrentCameraIds) {
for (auto& provider : mProviders) {
provider->getConcurrentCameraIds(concurrentCameraIds);
}
return OK;
}
四、相机权限与隐私保护
4.1 CAMERA 运行时权限
Android 6.0+ 的运行时权限模型要求 App 在首次使用相机前,通过 requestPermissions() 向用户申请 android.permission.CAMERA。
CameraService 在每次打开相机时都会校验权限:
// frameworks/av/services/camera/libcameraservice/CameraService.cpp
bool CameraService::hasPermissionsForCamera(int callingPid, int callingUid) {
// 使用 PermissionController 校验 CAMERA 权限
auto permController = mPermissionController;
if (permController->checkPermission("android.permission.CAMERA",
callingPid, callingUid)) {
return true;
}
// 系统 App 有额外的 SYSTEM_CAMERA 权限
if (permController->checkPermission("android.permission.SYSTEM_CAMERA",
callingPid, callingUid)) {
return true;
}
return false;
}
4.2 隐私指示器(Privacy Indicator)
Android 12 引入了相机/麦克风使用指示器(状态栏绿色圆点)。当任何 App 使用相机时,系统会自动显示隐私指示器:
// CameraService 在相机打开时通知隐私系统
void CameraService::updateCameraNumericHint(const std::string& cameraId,
bool inUse, int32_t clientUid) {
// 通知 AppOpsManager 相机开始使用(触发指示器)
auto appOps = mAppOps;
if (inUse) {
appOps->startOpNoThrow(AppOpsManager::OP_CAMERA, clientUid,
packageName, /*startIfModeDefault=*/false);
} else {
appOps->finishOp(AppOpsManager::OP_CAMERA, clientUid, packageName);
}
}
开发者注意:Android 12+ 的隐私指示器无法通过任何 API 屏蔽或延迟。只要相机处于活跃状态,指示器就会显示。这是刻意设计的——用户有权知道相机何时被使用。
4.3 相机访问审计
CameraService 会记录所有相机访问事件,可以通过 AppOpsManager 查询历史:
// 查询相机使用记录(需要 GET_APP_OPS_STATS 权限)
AppOpsManager appOps = getSystemService(AppOpsManager.class);
List<AppOpsManager.PackageOps> ops = appOps.getPackagesForOps(
new int[]{AppOpsManager.OP_CAMERA});
for (AppOpsManager.PackageOps pkgOps : ops) {
for (AppOpsManager.OpEntry op : pkgOps.getOps()) {
Log.d(TAG, pkgOps.getPackageName() +
" 最后使用相机: " + op.getLastAccessTime(AppOpsManager.OP_FLAGS_ALL));
}
}
五、性能、功耗与 Thermal 管理
5.1 相机启动延迟优化
相机启动延迟(从 openCamera() 调用到 onOpened() 回调)直接影响用户体验。主要耗时点:
- HAL Provider 初始化:约 50-200ms,取决于芯片和 ISP 初始化速度
- 相机驱动上电:约 20-50ms
- CameraService Binder 处理:约 1-5ms(可忽略)
Android 15 新增了相机预热(Camera Warm Up)机制,允许系统预测用户意图并提前初始化:
// Android 15 API(相机预热,降低实际打开延迟)
CameraManager manager = getSystemService(CameraManager.class);
// 提示系统:用户可能即将打开相机(例如用户刚双击电源键)
manager.reportCameraOpenIntent(cameraId);
// 系统可以提前给 HAL 上电,减少实际 openCamera() 的延迟
5.2 Thermal 限流机制
当设备温度过高时,CameraService 会主动降低相机输出能力,保护硬件并防止过热:
// frameworks/av/services/camera/libcameraservice/CameraService.cpp
void CameraService::onThermalChanged(hardware::thermal::V2_0::Temperature temp,
hardware::thermal::V2_0::ThrottlingSeverity severity) {
switch (severity) {
case ThrottlingSeverity::NONE:
// 正常状态,无限流
break;
case ThrottlingSeverity::LIGHT:
// 轻度限流:降低帧率(如 60fps → 30fps)
mCurrentThermalPolicy = ThermalPolicy::THROTTLE_MODERATE;
break;
case ThrottlingSeverity::MODERATE:
case ThrottlingSeverity::SEVERE:
// 严重限流:降低分辨率,或强制关闭某些相机流
mCurrentThermalPolicy = ThermalPolicy::THROTTLE_HEAVY;
break;
case ThrottlingSeverity::CRITICAL:
case ThrottlingSeverity::EMERGENCY:
// 紧急关闭:CameraService 强制断开所有相机连接
disconnectAllClients();
break;
}
// 通知所有活跃客户端限流状态变化
notifyClientsOfThermalThrottle(severity);
}
对应用开发者的影响:在高负载长时间录像场景(如 4K 30 分钟录制),可能收到 CameraDevice.StateCallback.onError() 带 ERROR_CAMERA_DEVICE 错误,或者预览帧率被自动降低。健壮的录像 APP 需要处理这些情况。
5.3 多摄像头功耗控制
同时开启多个摄像头(如前后置同时录制)会显著增加功耗。CameraService 会根据当前系统功耗状态控制相机的工作模式:
// CameraService 通知 HAL 进入节能模式
void Camera3Device::notifyIdleStatus() {
// 当没有活跃请求超过一定时间,通知 HAL 进入待机状态
// HAL 可以关闭 ISP 流水线,降低功耗
auto halInterface = mInterface;
halInterface->flush(); // 先清空 pipeline
// 传感器自动进入低功耗模式
}
六、实战案例:健壮的相机资源管理
基于以上原理,一个生产级的相机 APP 需要处理以下边界情况:
6.1 处理相机被抢占
class CameraManager {
private var cameraDevice: CameraDevice? = null
private val stateCallback = object : CameraDevice.StateCallback() {
override fun onOpened(camera: CameraDevice) {
cameraDevice = camera
startPreview(camera)
}
override fun onDisconnected(camera: CameraDevice) {
// 相机被其他高优先级 App 抢占(onDisconnected 必须处理!)
camera.close()
cameraDevice = null
// 通知用户相机被占用
runOnUiThread {
showMessage("相机已被其他应用占用")
// 注册可用性监听,等待相机恢复
cameraManager.registerAvailabilityCallback(availabilityCallback, null)
}
}
override fun onError(camera: CameraDevice, error: Int) {
camera.close()
cameraDevice = null
when (error) {
ERROR_CAMERA_IN_USE -> showMessage("相机已被占用")
ERROR_MAX_CAMERAS_IN_USE -> showMessage("已达到相机使用上限")
ERROR_CAMERA_DISABLED -> showMessage("相机已被系统禁用(隐私策略)")
ERROR_CAMERA_DEVICE -> showMessage("相机设备异常,请重启应用")
ERROR_CAMERA_SERVICE -> showMessage("相机服务异常,请重启手机")
}
}
}
// 注册相机可用性监听,当相机被释放后自动重试
private val availabilityCallback = object : CameraManager.AvailabilityCallback() {
override fun onCameraAvailable(cameraId: String) {
if (cameraId == targetCameraId) {
// 相机重新可用,尝试重新打开
openCamera()
}
}
}
}
6.2 正确释放相机资源
资源释放的顺序很重要——反序释放可能导致崩溃或资源泄漏:
fun releaseCamera() {
// 正确释放顺序(后进先出):
// 1. 停止 Repeating Request
captureSession?.stopRepeating()
// 2. 关闭 CaptureSession
captureSession?.close()
captureSession = null
// 3. 关闭 CameraDevice
cameraDevice?.close()
cameraDevice = null
// 4. 关闭 ImageReader(如有)
imageReader?.close()
imageReader = null
// 错误示范:先关闭 CameraDevice 再关闭 Session
// 这会导致 Session 的 onClosed() 回调在 Device 关闭后触发,
// 某些设备上可能引发 IllegalStateException
}
七、调试工具完全指南
7.1 dumpsys:全景快照
# 查看 CameraService 完整状态(最常用)
adb shell dumpsys media.camera
# 关键输出字段解读:
# == CameraService ==
# Number of camera devices: 3 ← 设备上的相机总数
# Active clients (1): ← 当前活跃的相机客户端数量
# Camera ID: 0
# Client UID: 10125 (com.example.camera)
# Client PID: 5678
# State: ACTIVE ← ACTIVE/IDLE
# Session configurations: 1 ← 当前会话数量
# 只看相机 ID 列表
adb shell dumpsys media.camera | grep "Camera device"
# 查看当前连接的所有客户端
adb shell dumpsys media.camera | grep -A 10 "Active clients"
# 查看 Provider 状态
adb shell dumpsys media.camera | grep -A 5 "Provider"
7.2 实时日志
# 相机服务核心日志
adb logcat -s CameraService:V CameraDeviceClient:V CameraProviderManager:V
# 过滤关键事件:打开/关闭/被抢占
adb logcat | grep -E "connect|disconnect|evict|openCamera|closeCamera"
# 查看权限相关
adb logcat | grep -E "CAMERA.*permission|hasPermissions"
# 查看优先级仲裁过程
adb logcat | grep -E "priority|evict|Higher-priority"
7.3 相机状态监控脚本
#!/bin/bash
# 每秒打印一次当前相机使用状态
while true; do
echo "=== $(date) ==="
adb shell dumpsys media.camera | grep -E "Active clients|Camera ID:|Client.*UID|State:"
echo ""
sleep 1
done
7.4 常见问题诊断
问题1:openCamera() 一直不回调(假死)
# 检查是否有进程持有锁
adb shell dumpsys media.camera | grep -E "Lock|Waiting|deadlock"
# 检查 HAL Provider 是否响应
adb logcat | grep "CameraProviderManager.*timeout"
# 常见原因:
# 1. HAL Provider crash 导致 service 无响应
# 2. SELinux 阻止了 cameraserver 访问设备节点
# 排查方案:adb shell dmesg | grep "avc: denied"
问题2:频繁被抢占(onDisconnected() 频繁触发)
# 查看是哪个 App 在抢占
adb logcat | grep "Evicting client"
# 输出类似:Evicting client for camera 0 due to higher priority app
# 查看系统进程状态
adb shell dumpsys activity processes | grep "proc state"
问题3:相机打开返回 ERROR_CAMERA_IN_USE
# 查看当前占用相机的应用
adb shell dumpsys media.camera | grep "Active clients" -A 20
# 找出占用的包名
adb shell dumpsys media.camera | grep "Client.*package"
# 如果没有 App 在使用但仍报错,说明有僵尸客户端(未正确释放)
# 解决方案:adb shell stop cameraserver && adb shell start cameraserver
# 注意:这会重启相机服务,会断开所有现有相机连接
7.5 Perfetto 相机性能分析
# 捕获 5 秒的相机性能 trace
adb shell perfetto \
--config - --txt \
-o /data/local/tmp/camera-perf.pb \
<<'EOF'
buffers: { size_kb: 65536 fill_policy: RING_BUFFER }
data_sources {
config {
name: "linux.ftrace"
ftrace_config {
ftrace_events: "camera/camera_capture_result_received"
ftrace_events: "camera/camera_capture_request_new"
ftrace_events: "camera/camera_capture_session_create"
}
}
}
data_sources {
config { name: "android.gpu.memory" }
}
duration_ms: 5000
EOF
# 拉取 trace 文件到本地
adb pull /data/local/tmp/camera-perf.pb ./camera-perf.pb
# 在 https://ui.perfetto.dev/ 中打开分析
八、Android 15 CameraService 新特性
8.1 Camera Access Callbacks 增强
Android 15 改进了相机访问回调,App 可以更精确地感知相机的开启/关闭事件:
// Android 15 新增 CameraManager.CameraAccessCallback
manager.registerCameraAccessCallback(executor, new CameraManager.CameraAccessCallback() {
@Override
public void onCameraOpened(@NonNull String cameraId, @NonNull String packageId) {
Log.d(TAG, "相机 " + cameraId + " 被 " + packageId + " 打开");
}
@Override
public void onCameraClosed(@NonNull String cameraId) {
Log.d(TAG, "相机 " + cameraId + " 已关闭");
}
});
8.2 Camera 抢占策略精细化
Android 15 允许系统 App 通过 CameraManagerGlobal 设置自定义抢占策略,适用于场景如:
- 视频通话应用(如 Google Meet)在录像时被拨入,允许自动暂停录像并切换到通话模式
- 特定 OEM 场景下的多应用相机协同
// 仅供系统 App 使用(需要 SYSTEM_CAMERA 权限)
// 声明此 App 支持相机共享(被抢占时不完全断开,而是降级为低优先流)
CameraManager.CameraAccessPrioritizationCallback callback =
new CameraManager.CameraAccessPrioritizationCallback() {
@Override
public void onAccessPriorityChanged(String cameraId, boolean isHighPriority) {
// 响应优先级变化,调整相机使用方式
}
};
总结
本文深入解析了 Android 15 CameraService 的核心架构:
- 四大模块:CameraDeviceClient(Binder 服务端)+ CameraProviderManager(HAL 管理)+ ClientManager(优先级仲裁)+ PermissionManager(权限/隐私)
- HAL Provider 体系:InternalCameraProvider(内置)、ExternalCameraProvider(USB热插拔)、LegacyCameraProvider(兼容)三类 Provider
- 优先级仲裁:基于 AMS 进程状态的优先级数值,数值越小优先级越高;高优先级 App 可强制抢占低优先级 App 的相机
- 隐私保护:权限校验 + AppOps 审计 + 状态栏隐私指示器三层机制
- Thermal 限流:从轻度降帧到严重关机,六级 Thermal 策略保护硬件
- 健壮 App 实践:正确处理
onDisconnected()和onError(),按序释放资源
理解 CameraService 的架构,对调试"相机打不开"、"相机被抢占"、"录像异常中断"等问题至关重要。
参考资料
- Android Camera Architecture — 官方架构文档
frameworks/av/services/camera/libcameraservice/CameraService.cpp— 服务主入口frameworks/av/services/camera/libcameraservice/common/CameraProviderManager.cpp— Provider 管理frameworks/av/services/camera/libcameraservice/utils/ClientManager.cpp— 客户端优先级仲裁frameworks/av/camera/cameraserver/main_cameraserver.cpp— 进程启动入口