Treble 架构下的 Android Camera 框架

Camera HAL 新架构

  1. Camera 子系统从上到下分别是 App/FrameworkCameraServiceHAL Impl
  2. App/Framework vs CameraService 之间,通过 AIDL binder 通信
  3. CameraService vs Camera HAL 之间,通过 HIDL binder 通信

     

App Framework 部分是最上层部分,包括 Java & C++ 代码,实现了 Android Camera2 API 接口,提供给 android 应用使用,Java 部分包含在 Android SDK 里面。

source tree

CameraService 是中间桥梁,负责沟通 Framework 与 Camera 硬件设备,把上层的调用需求透过 camera hal 接口转发给 HAL 硬件实现,同时返回处理结果。

source tree

Camera HAL 是硬件适配层,针对不同 camera 硬件模组,由 OEM 厂商提供具体实现

source tree

 

cameraserver

frameworks/av/camera/cameraserver/main_cameraserver.cpp

frameworks/av/camera/cameraserver/cameraserver.rc

1
2
3
4
5
6
7
service cameraserver /system/bin/cameraserver
    class main
    user cameraserver
    group audio camera input drmrpc
    ioprio rt 4
    task_profiles CameraServiceCapacity MaxPerformance
    rlimit rtprio 10 10

 

 HAL Impl

Camera Provider 实现

首先,实现 hal 独立运行的进程,并向 hwservicemanager 注册 ICameraProvider 服务,对上层提供硬件功能,包括设备状态信息的查询/更新,获取设备接口以便可以调用设备功能。

AOSP 代码目前有两个 ICameraProvider 服务进程:

  • legacy/0, 给内置相机用, 所以目前为止,Camera HALv3 实现还是属于传统 HAL,参考HAL 类型
  • external/0, Android P 新增的调用外接 usb 相机的 HAL 服务进程

它们都有对应的启动脚本,在系统启动时加载运行。所以内置相机外接相机的HAL 实现是分别在两个不同进程里面,各自独立互不影响!

如果需要还可以扩展更多 camera provider,比如 internallegacyexternalremote 等等,只要具备以下几个条件,cameraservice 就能透过 CameraProviderManager 查询到该服务并查询到 camera 设备列表,供 App Framework 使用该相机设备:

  • 启动脚本
  • 启动 binary,调用 defaultPassthroughServiceImplementation 注册服务
  • manifest camera.provider 节点声明,包括 ßtransport 类型和 instance 实例节点名称

进程启动时,会完成这么几件事,跟 hwservicemanager以及PassthroughServiceManager的交互通过 binder IPC 调用完成

  1. 确保 /dev/vndbinder 对应的 binder 服务进程已经启动,如果没有则启动它
  2. 在该进程里透过 android_dlopen_ext/dlopen 加载对应版本的库,这里是android.hardware.camera.provider@2.4-impl.so
  3. 透过 dlsym 获取到 HIDL_FETCH_ICameraProvider 方法,然后遍历 manifest 里面 camera.provider 这个 hidl 接口声明的 instance 实例名称,作为参数调用该方法, 即可获取到该实例对应的 ICameraProvider 实现
  4. 向 hwservicemanager 注册该服务:
    • 首先在 hwservicemanager 中插入一个 HidlService (interfaceName, instanceName)
    • 其次生成的 CameraProvider 对象也要透过 IPC 调用 hidl::manager::add 把自己添加到 hwservicemanager,因为上一步已经插入了一个对应的 HidlService 所以仅仅是更新 pid和 service 指向实例对象
    • (interfaceName, instanceName) 对应 internal camera provider 就是 (“android.hardware.camera.provider@2.4::ICameraProvider”, “/legacy/0”),

这几个步骤都在当前启动的进程里面调用 defaultPassthroughServiceImplementation 完成的,所以调用过程中透过 IPCThreadState::self()->getCallingPid() 获取到当前进程的pid,也就是提供服务的进程。

详细代码可以跟踪该函数查阅,另外还要参考 hardware/interfaces/camera 源代码下面 *.hal 编译时由 hidl-gen 生成的中间源代码

HidlService 保持的信息如下,包括接口名称实例名称实例对象, HAL进程pid

struct HidlService {
    HidlService(const std::string &interfaceName,
                const std::string &instanceName,
                const sp<IBase> &service,
                const pid_t pid);
    HidlService(const std::string &interfaceName,
                const std::string &instanceName)
    : HidlService(
        interfaceName,
        instanceName,
        nullptr,
        static_cast<pid_t>(IServiceManager::PidConstant::NO_PID))
    {}
    virtual ~HidlService() {}
    ...

这里可以看到,同一个 hidl 接口,可以有多个实例实现,对应不同类型的硬件设备,比如这里 /legacy/0 对应内置相机,/external/0 对应外接 usb 相机,它们的 interfaceName 一样,instanceName 不一样。并且各自有自己的独立进程。

camera.provider 接口声明,包括 transport 是 hwbinder, 实例有两个 legacy/0external/0

manifest.xml :

<hal format="hidl">
    <name>android.hardware.camera.provider</name>
    <transport>hwbinder</transport>
    <version>2.4</version>
    <interface>
        <name>ICameraProvider</name>
        <instance>legacy/0</instance>
        <instance>external/0</instance>
    </interface>
    <fqname>@2.4::ICameraProvider/legacy/0</fqname>
</hal>

hardware/interfaces/camera/provider/2.4/default/service.cpp
 

int main()
{
    ALOGI("CameraProvider@2.4 legacy service is starting.");
    // The camera HAL may communicate to other vendor components via
    // /dev/vndbinder
    android::ProcessState::initWithDriver("/dev/vndbinder");
    status_t status;
    if (kLazyService) {
        status = defaultLazyPassthroughServiceImplementation<ICameraProvider>("legacy/0",
                                                                              /*maxThreads*/ 6);
    } else {
        status = defaultPassthroughServiceImplementation<ICameraProvider>("legacy/0",
                                                                          /*maxThreads*/ 6);
    }
    return status;
}

hardware/interfaces/camera/provider/2.4/default/external-service.cpp
 

int main()
{
    ALOGI("External camera provider service is starting.");
    // The camera HAL may communicate to other vendor components via
    // /dev/vndbinder
    android::ProcessState::initWithDriver("/dev/vndbinder");
    return defaultPassthroughServiceImplementation<ICameraProvider>("external/0", /*maxThreads*/ 6);
}

注意下面 extern "C" 的声明,确保 C++ 符合没有做 name mangling 处理,保持原样,确保服务进程启动时可以透过 dlsym 获取到 HIDL_FETCH_Interface 并构造服务实例对象,然后向hwservicemanager注册该服务。

同时 CameraProvider 类的实现是一个模板类工厂,根据不同模板参数创建对应的类实例。

hardware/interfaces/camera/provider/2.4/default/CameraProvider_2_4.cpp




 

  • 0
    点赞
  • 8
    收藏
    觉得还不错? 一键收藏
  • 2
    评论
评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值