CameraService服务管理:Android相机资源的"大管家"

0 阅读15分钟

引言:谁来仲裁相机资源争夺战?

想象这样一个场景:你正在用第三方相机 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 内部由四个核心模块组成,各司其职:

02-01-cameraservice-architecture.png

模块对应类核心职责
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 类型类名说明
内置相机 ProviderInternalCameraProvider管理前置/后置摄像头,最常见
外接相机 ProviderExternalCameraProvider管理 USB 外接摄像头,支持热插拔
旧版兼容 ProviderLegacyCameraProvider为 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 同时竞争相机时,谁赢谁输?

02-02-multi-app-arbitration.png

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() 回调)直接影响用户体验。主要耗时点:

  1. HAL Provider 初始化:约 50-200ms,取决于芯片和 ISP 初始化速度
  2. 相机驱动上电:约 20-50ms
  3. 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 的核心架构:

  1. 四大模块:CameraDeviceClient(Binder 服务端)+ CameraProviderManager(HAL 管理)+ ClientManager(优先级仲裁)+ PermissionManager(权限/隐私)
  2. HAL Provider 体系:InternalCameraProvider(内置)、ExternalCameraProvider(USB热插拔)、LegacyCameraProvider(兼容)三类 Provider
  3. 优先级仲裁:基于 AMS 进程状态的优先级数值,数值越小优先级越高;高优先级 App 可强制抢占低优先级 App 的相机
  4. 隐私保护:权限校验 + AppOps 审计 + 状态栏隐私指示器三层机制
  5. Thermal 限流:从轻度降帧到严重关机,六级 Thermal 策略保护硬件
  6. 健壮 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 — 进程启动入口