当前位置: 首页 > news >正文

Android Camera 从应用到硬件之- 枚举Camera - 1

缘起何处

废话不多说, 相信时间的力量,开干!

从五年前就开始认识camera到目前的一知半解,实在是惭愧.于是决定再上路.可能是有点晚了, 但是later is bettern than never!

最早接触camera是高通的660 mm-camera结构.已经全部忘了, 但是Android9 从上到下的camera架构毕竟还是走过看过的. 

那就从,API说起. 翻一下Android15的源码, 走一下核心接口的过程.

以下内容很多是基于AI生成内容进行的二次改动!

CameraService继承多虚父类的设计目的

CameraService 继承多个类(包括虚基类,即带有 virtual 关键字的父类)是 Android 框架设计中功能聚合与接口适配的典型体现。这些父类分别提供了不同的核心能力,通过多继承,CameraService 能够整合多种功能,同时满足系统框架对接口规范、通信机制、生命周期管理等多方面的要求。

具体继承的类及其作用分析

1. BinderService<CameraService>

  • 核心作用:提供 Binder 服务的基础框架,简化服务注册、生命周期管理等流程。
  • BinderService 是一个模板类,封装了 Binder 服务的通用逻辑(如通过 instantiate() 方法注册服务到 servicemanager)。CameraService 继承它后,无需重复实现服务注册的底层细节,只需专注于相机业务逻辑。

2. ::android::hardware::BnCameraService

  • 核心作用:实现 Binder 通信的服务端接口,提供跨进程调用(IPC,进程通信)能力。
  • BnCameraService 是相机服务的 Binder 接口基类(由 ICameraService.aidl 自动生成),其中定义了相机服务对外提供的所有接口(如打开相机、枚举相机设备等)。继承此类后,CameraService 需实现这些纯虚函数,从而支持上层应用(如相机 App)通过 Binder 机制调用相机服务。

3. IBinder::DeathRecipient

  • 核心作用:监听其他 Binder 对象的死亡通知,处理客户端或依赖服务崩溃的场景。
  • 相机服务需要与多个客户端(如应用进程)、子服务(如相机提供商 CameraProvider)通过 Binder 交互。若对方进程崩溃,DeathRecipient 的 binderDied() 方法会被回调,CameraService 可通过重写该方法释放相关资源(如关闭相机设备、清理客户端状态),避免资源泄漏或野指针错误。

4. CameraProviderManager::StatusListener

  • 核心作用:监听相机硬件提供商(CameraProvider)的状态变化,同步硬件状态。
  • CameraProviderManager 是管理相机 HAL 层提供商的模块(负责加载、管理相机硬件抽象)。StatusListener 定义了硬件状态变化的回调接口(如相机设备连接 / 断开、硬件故障等)。CameraService 继承此类后,可实时感知硬件状态变化(如外接相机插入),并同步更新服务内部状态(如刷新相机列表),确保上层获取的信息与硬件一致。

5. IServiceManager::LocalRegistrationCallback

  • 核心作用:监听服务自身在 servicemanager 中的注册状态,处理注册成功 / 失败的回调。
  • 当 CameraService 注册到系统服务管理器(servicemanager)时,LocalRegistrationCallback 的方法(如 onRegistrationCompleted())会被触发。通过重写这些方法,CameraService 可在注册成功后执行初始化操作(如加载 HAL 模块),或在注册失败时进行错误处理(如重试、上报日志)。

为什么需要 “虚继承”?

代码中使用 public virtual 继承(虚继承),主要是为了解决多继承可能导致的 “菱形继承” 问题

  • 若多个父类间接继承自同一个基类(如 Binder 相关的父类可能共同继承自 IBinder),非虚继承会导致基类成员在子类中存在多份拷贝,引发二义性。
  • 虚继承确保所有父类共享同一个基类实例,避免数据冗余和访问冲突,这在复杂的多继承场景(如 Android 服务框架)中是必要的设计。

CameraService 继承多个类是 **“组合复用” 设计原则 ** 的体现:每个父类封装特定功能(Binder 通信、死亡监听、硬件状态同步等),通过多继承将这些功能聚合到 CameraService 中,使其既能满足系统框架的接口规范,又能高效处理相机服务的核心业务(硬件交互、客户端管理、跨进程通信等)。这种设计避免了代码冗余,同时保证了系统各模块的解耦与可扩展性。

枚举Camera

在 Android 相机框架中,enumerateProviders() 是 CameraProviderManager 类的核心方法,其主要作用就是枚举系统中可用的相机提供商(Camera Provider),而相机提供商是连接相机硬件与框架层的关键组件,因此该方法间接实现了相机设备的枚举。

具体逻辑解析:

  1. 什么是 “相机提供商(Camera Provider)”?在 Android 8.0(API 26)引入的 Camera HAL 3.2+ 架构中,相机硬件的抽象被封装为 “相机提供商”(通常是运行在 camera-provider 进程中的 HAL 服务),每个提供商负责管理一组物理相机(如手机的后置主摄、超广角、前置摄像头等)。例如,高通平台的 camera-provider-2-4 就是一个典型的相机提供商,管理该平台上的所有摄像头硬件。

  2. enumerateProviders() 的核心作用该方法会通过 HIDL(Android 硬件接口定义语言) 扫描系统中已注册的所有相机提供商(通过 IServiceManager 查找符合相机接口规范的服务),并执行以下操作:

    • 收集每个提供商的信息(如名称、版本、支持的相机功能);
    • 调用提供商的 getCameraIdList() 接口,获取其管理的所有物理相机 ID(如 “0”“1”“2”,分别对应不同摄像头);
    • 将相机 ID 与提供商信息关联,形成 “相机设备列表”,供上层 CameraService 使用。
  3. 与 “相机枚举” 的关系

    • enumerateProviders() 本身不直接枚举物理相机,而是枚举管理相机的 “提供商”
    • 但通过枚举提供商并调用其接口,间接完成了物理相机的枚举(获取所有可用相机的 ID 和基础信息);
    • 最终,CameraService 会基于 enumerateProviders() 的结果,向上层应用(如相机 App)提供可用相机列表(即用户在 App 中看到的 “切换摄像头” 选项)。

调用时机与意义

enumerateProviders() 通常在 CameraService 初始化阶段被调用(如 CameraService::onFirstRef() 中),是系统启动时 “发现相机设备” 的关键步骤。如果该方法执行失败(如没有找到任何相机提供商),系统会提示 “无可用相机”。

enumerateProviders() 是 Android 相机框架中相机枚举的 “上游步骤”:通过枚举相机提供商,间接获取所有物理相机的信息,为上层提供可用相机列表。可以说,它是相机设备能够被系统识别和使用的基础。

status_t CameraService::enumerateProviders() {  //provider是连接相机硬件和框架层的关键组件,该方法间接的实现了相机的枚举.status_t res;std::vector<std::string> deviceIds;std::unordered_map<std::string, std::set<std::string>> unavailPhysicalIds;{Mutex::Autolock l(mServiceLock);if (nullptr == mCameraProviderManager.get()) {mCameraProviderManager = new CameraProviderManager();res = mCameraProviderManager->initialize(this); //初始化接口.if (res != OK) {ALOGE("%s: Unable to initialize camera provider manager: %s (%d)",__FUNCTION__, strerror(-res), res);logServiceError(String8::format("Unable to initialize camera provider manager"),ERROR_DISCONNECTED);return res;}}// Setup vendor tags before we call get_camera_info the first time because HAL might need to setup static vendor keys in get_camera_info TODO: maybe put this into CameraProviderManager::initialize()?mCameraProviderManager->setUpVendorTags();if (nullptr == mFlashlight.get()) {mFlashlight = new CameraFlashlight(mCameraProviderManager, this);}res = mFlashlight->findFlashUnits();if (res != OK) {ALOGE("Failed to enumerate flash units: %s (%d)", strerror(-res), res);}deviceIds = mCameraProviderManager->getCameraDeviceIds(&unavailPhysicalIds);}for (auto& cameraId : deviceIds) {String8 id8 = String8(cameraId.c_str());if (getCameraState(id8) == nullptr) {onDeviceStatusChanged(id8, CameraDeviceStatus::PRESENT);}if (unavailPhysicalIds.count(cameraId) > 0) {for (const auto& physicalId : unavailPhysicalIds[cameraId]) {String8 physicalId8 = String8(physicalId.c_str());onDeviceStatusChanged(id8, physicalId8, CameraDeviceStatus::NOT_PRESENT);}}}// Derive primary rear/front cameras, and filter their charactierstics.// This needs to be done after all cameras are enumerated and camera ids are sorted.if (SessionConfigurationUtils::IS_PERF_CLASS) {// Assume internal cameras are advertised from the same// provider. If multiple providers are registered at different time,// and each provider contains multiple internal color cameras, the current// logic may filter the characteristics of more than one front/rear color// cameras.Mutex::Autolock l(mServiceLock);filterSPerfClassCharacteristicsLocked();}return OK;
}

http://www.dtcms.com/a/537144.html

相关文章:

  • 【Frida Android】基础篇13:Frida-Trace 基础简介——从命令到脚本的动态追踪入门
  • 使用electron-vite生成一个桌面应用以及引入必要插件
  • 龙岗网站设计机构网络培训平台建设方案
  • 运动想象 (MI) 分类学习系列 (19) : EEG-TransNet
  • io游戏网站重庆市建设项目环境影响评价网站
  • 怎样做静态网站做网站开发用哪门语言
  • springAI实现ai大模型+传统应用双剑合璧- Function Calling
  • 电子商务网站开发设计适合前端新手做的网页
  • 济宁市建设局网站wordpress hover
  • 熵平衡机制在子种群迁移中的具体实现
  • 记录一下Linux 6.12 中 cpu_util函数的作用
  • 做淘宝内部优惠券网站要钱么网站制作费用价格表
  • ECSCluster容器洞察功能完整实现与深度解析
  • 力扣(LeetCode) ——15.三数之和(C++)
  • Kubernetes GPU 运维组件介绍
  • 龙中龙网站开发wordpress 判断函数
  • 网站开发流程框架手机软件开发和网站开发
  • 定时发布文章测试
  • 联邦快递网站建设的目标重庆平台网站推广
  • 医院 网站建设成品网站价格表
  • 第14天:系统监控与日志管理
  • 区块链分层架构或侧链/子链
  • Ethernaut Level 14: Gatekeeper Two - 合约创建时的 extcodesize
  • 网页网站建设难吗深圳网络营销推广公司
  • 东莞网站开发深圳做网站做app
  • 18.矩阵置零(原地算法)
  • Lambda表达式的使用
  • Pinterest Data Scientist 面试经验分享|数据分析 + 实验设计 + 产品洞察并重
  • 重庆璧山网站建设营销型网站的建设流程
  • 做网站用什么软件ps字体文化公司网页设计