Android 8.0 Camera架构源码分析 - CameraProvider And CameraService启动

前一篇文章主要是android 7之前的流程,这篇看看android 8之后有哪里变化,对比会更能理解代码流程:

Camera 服务启动流程概览
在 Android O 中,系统启动时,就会启动 CameraProvider 服务。它将 Camera HAL 从 cameraserver 进程中分离出来,作为一个独立进程 android.hardware.camera.provider@2.4-service 来控制 HAL。 
这两个进程之间通过 HIDL 机制进行通信。

这样的改动源自于 Android O 版本加入的 Treble 机制,它的主要功能(如下图所示)是将 service 与 HAL 隔离,以方便 HAL 部分进行独立升级。这其实和 APP 与 Framework 之间的 Binder 机制类似,通过引入一个进程间通信机制而针对不同层级进行解耦(从 Local call 变成了 Remote call)。 

如此一来 Camera 服务的启动流程就变得有些复杂了,但是最核心的部分其实没变,最终都要从动态库中获取连接 HAL 的结构,并保存下来以备未来对 Camera 设备进行操作。 
这几天跟了一下代码流程,大概总结了一下 cameraserver 与 provider 这两个进程启动、初始化的调用逻辑,如下图。 

总体逻辑顺序:

  1. provider 进程启动,注册;
  2. cameraserver 进程启动,注册,初始化;
  3. cameraserver 获取远端 provider(此时实例化 CameraProvider 并初始化)。、

上图中,实线箭头是调用关系。左边是 cameraserver 进程中的动作,右边则是 provider 进程中的动作,它们之间通过 ICameraProvider 联系在了一起,而这个东西与 HIDL 相关,我们可以不用关心它的实现方式。

由图可见:

cameraserver 一侧,Cameraservice 类依旧是主体。它通过 CameraProviderManager 来管理对 CameraProvider 的操作。此处初始化的最终目的是连接上 CameraProvider
provider 一侧,最终主体是 CameraProvider。初始化最终目的是得到一个 mModule,通过它可以直接与 HAL 接口定义层进行交互。

至此,我们就能对 Android O 上的 Camera 服务启动流程有一个大致的了解。但由于我个人功力尚浅,目前只能理解到这个地步,还无法轻易抽象出更容易理解的框架,所以图片中的流程还是比较凌乱的,可能需要对照相应代码才能理解。

下面是我分析代码时的一些笔记,有需要可以对照上图中的流程看看。

1. CameraProvider 的启动与注册

这个服务进程的启动很简单,主要动作是注册该 CameraProvider,以便 CameraServer 启动时能找到它。需要注意的是,此时 CameraProvider 还未实例化与初始化。

首先看下camera provider所在源码中的位置:hardware/interfaces/camera/provider/

hardware/interfaces/camera/provider$ tree
.
├── 2.4
│   ├── Android.bp
│   ├── default
│   │   ├── Android.bp
│   │   ├── android.hardware.camera.provider@2.4-service.rc
│   │   ├── CameraProvider.cpp
│   │   ├── CameraProvider.h
│   │   ├── OWNERS
│   │   └── service.cpp
│   ├── ICameraProviderCallback.hal
│   ├── ICameraProvider.hal
│   └── vts
│       ├── functional
│       │   ├── Android.bp
│       │   └── VtsHalCameraProviderV2_4TargetTest.cpp
│       └── OWNERS
└── README.md

可以看出来在hardware/interfaces/camera/provider/2.4/default/ 下面有几个rc文件,Android初始化就是执行这些rc文件,这里执行的是android.hardware.camera.provider@2.4-service.rc文件,看看其中的执行代码。

service camera-provider-2-4 /vendor/bin/hw/android.hardware.camera.provider@2.4-service
    class hal
    user cameraserver
    group audio camera input drmrpc inet
    ioprio rt 4
    capabilities SYS_NICE
    writepid /dev/cpuset/camera-daemon/tasks /dev/stune/top-app/tasks

第一行就看到了启动一个 /vendor/bin/hw/android.hardware.camera.provider@2.4-service 进程

Service.cpp

文件位置:hardware/interfaces/camera/provider/2.4/default

看代码:

第6行:初始化binder通信驱动节点,打开binder设备
第7行:创建默认为直通模式(Passthrough)的CameraProvider服务实现

int main()
{
    ALOGE("luozh Camera provider Service is starting.");
    // The camera HAL may communicate to other vendor components via
    // /dev/vndbinder
    android::ProcessState::initWithDriver("/dev/binder");
    return defaultPassthroughServiceImplementation<ICameraProvider>("legacy/0", /*maxThreads*/ 6);
}

defaultPassthroughServiceImplementation的实现在:

LegacySupport.h

文件路径:system/libhidl/transport/include/hidl

该函数做了这些事:

第 5 行:配置 RPC 线程池(当前设置最大线程为 6)。
第 6 行:将 Interface(即 CameraProvider)以入参 legacy/0 为名注册到相应的管理服务中。
第 12 行:连接到线程池。

template<class Interface>
__attribute__((warn_unused_result))
status_t defaultPassthroughServiceImplementation(std::string name,
                                            size_t maxThreads = 1) {
    configureRpcThreadpool(maxThreads, true);
    status_t result = registerPassthroughServiceImplementation<Interface>(name);

    if (result != OK) {
        return result;
    }

    joinRpcThreadpool();
    return 0;
}

2. CameraService 的启动与初始化

      一般来说应该是 Provider 服务先启动,然后 Cameraserver 再启动,并 ”连接“ 到 Provider。 
前面已经分析了 Provider 的启动,现在就来看看 Cameraserver 的启动流程。

此处的分析详细可看文章https://blog.csdn.net/bailang9757/article/details/93073769

main_cameraserver.cpp

文件位置:frameworks/av/camera/cameraserver

关于线程池配置的部分就忽略吧,主要关注第 11 行,在该进程中实例化了 CameraService。
实例化只有简单的一行代码,但实例化的过程并不那么简单。这个 instantiate() 接口并不是定义在 CameraService 类中的,而是定义在 BinderService 类里(而 CameraService 继承了它)。在此处,它的作用是创建一个 CameraService(通过 new 的方式),并将其加入到 ServiceManager 中(注意,在这一过程中,CameraService 被强指针引用了)。

int main(int argc __unused, char** argv __unused)
{
    signal(SIGPIPE, SIG_IGN);
 
    // Set 3 threads for HIDL calls
    hardware::configureRpcThreadpool(3, /*willjoin*/ false);
 
    sp<ProcessState> proc(ProcessState::self());
    sp<IServiceManager> sm = defaultServiceManager();
    ALOGI("ServiceManager: %p", sm.get());
    //初始化CameraService服务
    CameraService::instantiate();
    ProcessState::self()->startThreadPool();
    IPCThreadState::self()->joinThreadPool();
}

CameraService.cpp

文件位置:frameworks/av/services/camera/libcameraservice/CameraService.cpp

void CameraService::onFirstRef()
{
    ALOGI("CameraService process starting");

    BnCameraService::onFirstRef();

    // Update battery life tracking if service is restarting
    BatteryNotifier& notifier(BatteryNotifier::getInstance());
    notifier.noteResetCamera();
    notifier.noteResetFlashlight();

    status_t res = INVALID_OPERATION;

    res = enumerateProviders();
    if (res == OK) {
        mInitialized = true;
    }

    CameraService::pingCameraServiceProxy();
}

Note: 明显看出来此处和Android7.0,即前篇文章讲解的此处函数的不同

enumerateProviders

函数内容略多,所以只截取需要重点关注的部分。
首先将 CameraProviderManager 实例化(第 6 行),然后调用 initialize() 接口将其初始化(第 7 行),传入的参数是 this 指针,指向当前 CameraService 实例的地址。

status_t CameraService::enumerateProviders() {
    status_t res;
    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);
            return res;
        }
    }
    ...
}

CameraProviderManager.cpp

文件位置:frameworks/av/services/camera/libcameraservice/common

initialize

在分析具体实现之前,可以先看看它在头文件中的声明:

用于初始化管理器,并给它设置一个状态监听(即 CameraService 实例)。选择性地接受一个与服务交互的代理。
默认的代理通过 Hardware 服务管理器进行通信。备用的代理可以用来进行测试。代理的生命周期必须要超过管理器的生命周期。
注意到在 enumerateProviders 中调用该接口时,只有一个入参,说明当前用的是默认代理。

/**
     * Initialize the manager and give it a status listener; optionally accepts a service
     * interaction proxy.
     *
     * The default proxy communicates via the hardware service manager; alternate proxies can be
     * used for testing. The lifetime of the proxy must exceed the lifetime of the manager.
     */
    status_t initialize(wp<StatusListener> listener,
            ServiceInteractionProxy *proxy = &sHardwareServiceInteractionProxy);

接下来看看具体实现的逻辑:

第 11~19 行:通过服务代理作出一个注册动作。根据注释,注册会触发一个给所有已知 Provider 进行通知的动作。
第 22 行:这是我们主要关注的函数。注释翻译过来是这样,看看这是否为一个直通的 HAL,如果不是也没关系。注意传入的参数 kLegacyProviderName,在文件开头有它的定义,即为字符串 legacy/0。

status_t CameraProviderManager::initialize(wp<CameraProviderManager::StatusListener> listener,
        ServiceInteractionProxy* proxy) {
    std::lock_guard<std::mutex> lock(mInterfaceMutex);
    if (proxy == nullptr) {
        ALOGE("%s: No valid service interaction proxy provided", __FUNCTION__);
        return BAD_VALUE;
    }
    mListener = listener;
    mServiceProxy = proxy;

    // Registering will trigger notifications for all already-known providers
    bool success = mServiceProxy->registerForNotifications(
        /* instance name, empty means no filter */ "",
        this);
    if (!success) {
        ALOGE("%s: Unable to register with hardware service manager for notifications "
                "about camera providers", __FUNCTION__);
        return INVALID_OPERATION;
    }

    // See if there's a passthrough HAL, but let's not complain if there's not
    addProviderLocked(kLegacyProviderName, /*expected*/ false);

    return OK;
}

addProviderLocked

这个函数主要作用是将找到的这个 Provider 通过 ProviderInfo 记录下来并初始化。

第 2~8 行:检查已知的 Provider 中是否已有名为 legacy/0 的。
第 10~21 行:根据 legacy/0 从服务代理处获取 CameraProvider 接口,这里需要特别注意,因为此处真正地初始化了对应的 CameraProvider(怎么就在这初始化了?下一节继续分析)。
第 23~28 行:通过 ProviderInfo 来保存当前 Provider 相关信息。
第 30 行:记录当前 Provider。

status_t CameraProviderManager::addProviderLocked(const std::string& newProvider, bool expected) {
    for (const auto& providerInfo : mProviders) {
        if (providerInfo->mProviderName == newProvider) {
            ALOGW("%s: Camera provider HAL with name '%s' already registered", __FUNCTION__,
                    newProvider.c_str());
            return ALREADY_EXISTS;
        }
    }

    sp<provider::V2_4::ICameraProvider> interface;
    interface = mServiceProxy->getService(newProvider);

    if (interface == nullptr) {
        if (expected) {
            ALOGE("%s: Camera provider HAL '%s' is not actually available", __FUNCTION__,
                    newProvider.c_str());
            return BAD_VALUE;
        } else {
            return OK;
        }
    }

    sp<ProviderInfo> providerInfo =
            new ProviderInfo(newProvider, interface, this);
    status_t res = providerInfo->initialize();
    if (res != OK) {
        return res;
    }

    mProviders.push_back(providerInfo);

    return OK;
}

CameraProvider 的初始化

在 CameraService 的初始化过程中,CameraProvider 才开始进行初始化,只不过这个初始化是通过服务代理进行远端调用而进行的。

在 CameraProviderManager::addProviderLocked 函数的实现逻辑中,调用了 ICameraProvider::getService 接口,该接口最终会调用到一个名为 HIDL_FETCH_ICameraProvider 的函数。

CameraProvider.cpp

文件位置:hardware/interfaces/camera/provider/2.4/default

HIDL_FETCH_ICameraProvider
若传入的参数是 legacy/0,则创建一个 CameraProvider 实例(构造函数中调用了它自身的初始化函数)并返回相应指针给函数调用者。

ICameraProvider* HIDL_FETCH_ICameraProvider(const char* name) {
    if (strcmp(name, kLegacyProviderName) != 0) {
        return nullptr;
    }
    CameraProvider* provider = new CameraProvider();
    if (provider == nullptr) {
        ALOGE("%s: cannot allocate camera provider!", __FUNCTION__);
        return nullptr;
    }
    if (provider->isInitFailed()) {
        ALOGE("%s: camera provider init failed!", __FUNCTION__);
        delete provider;
        return nullptr;
    }
    return provider;
}
CameraProvider::CameraProvider() :
        camera_module_callbacks_t({sCameraDeviceStatusChange,
                                   sTorchModeStatusChange}) {
    mInitFailed = initialize();
}

initialize()

整个函数实现比较冗长,只贴出我们需要关注的部分分析。

第 1~7 行:需要注意 rawModule 这个指针指向的结构,通过 hw_get_module 函数获取到它的实例(从相应的 Camera HAL 动态库中加载得到)。实际上这个结构就是连接到 HAL 层的关键点,通过它就可以调用到 HAL 中的一些函数。
(关于 hw_get_module,我以前分析过 Android N 上相关的逻辑,在 O 上其实没有很大改动,如果要详细了解可以去看看那篇文章)
第 9~15 行:基于 rawModule 创建 CameraModule 实例并初始化。之后都是通过 mModule 来对 HAL 进行操作的。(其实 CameraModule 是对于 camera_module_t 的一层封装,诸如 init、open 这样的操作,实际上都是通过调用 camera_module_t 结构中函数指针指向的 HAL 层的具体实现函数来完成的)
执行完这个函数,CameraProvider 也就随之初始化完成了。

camera_module_t *rawModule;
int err = hw_get_module(CAMERA_HARDWARE_MODULE_ID,
        (const hw_module_t **)&rawModule);
//rawModule指向了Hal层的hw_module_t camera_common{}地址,后面可以以此操作hal层,
//注意这里把rawModule强转成hw_module_t,至于为什么能强转,另一篇文章里面已经左分析,可以参看
if (err < 0) {
    ALOGE("Could not load camera HAL module: %d (%s)", err, strerror(-err));
    return true;
}

//创建CameraModule对象并初始化
mModule = new CameraModule(rawModule);
err = mModule->init();
if (err != OK) {
    ALOGE("Could not initialize camera HAL module: %d (%s)", err, strerror(-err));
    mModule.clear();
    return true;
}
ALOGI("Loaded \"%s\" camera module", mModule->getModuleName());

此处就和android 7.0 CameraService::onFirstRef()函数里面实现的完全一样了,之前这部分是在cameraservice线程里实现,现在分开了(https://blog.csdn.net/bailang9757/article/details/93073769

CameraModule.cpp

文件位置:hardware/interfaces/camera/common/1.0/default/CameraModule.cpp

构造函数:注意,这里的 mModule 是 camera_module_t 类型

CameraModule::CameraModule(camera_module_t *module) {
    if (module == NULL) {
        ALOGE("%s: camera hardware module must not be null", __FUNCTION__);
        assert(0);
    }
    mModule = module;
}

init(): 

  • 调用 mModule 的 init() 函数。
  • 如果没有指定的 init() 函数,则 init 流程到这里就可以结束了。
int CameraModule::init() {
    ATRACE_CALL();
    int res = OK;
    ALOGE("luozh CameraModule::init() --- >>");
    if (getModuleApiVersion() >= CAMERA_MODULE_API_VERSION_2_4 &&
            mModule->init != NULL) {
        ATRACE_BEGIN("camera_module->init");
        res = mModule->init();//具体库里面的  hal
        ATRACE_END();
    }
    mCameraInfoMap.setCapacity(getNumberOfCameras());
    return res;
}

mModle->init就到具体Hal的:

camera_module_t HAL_MODULE_INFO_SYM = { 
    .common                 = camera_common,
    .get_number_of_cameras  = XX::Camera2Factory::get_number_of_cameras,
    .get_camera_info        = XX::Camera2Factory::get_camera_info,
    .set_callbacks          = XX::Camera2Factory::set_callbacks,
    .get_vendor_tag_ops     = XX::Camera3VendorTags::get_vendor_tag_ops,
    .open_legacy            = NULL,
    .set_torch_mode         = XX::Camera2Factory::set_torch_mode,
    .init                   = NULL,
    .reserved               = {0} 
};

小结
在 Android O 之前,Service 与 HAL 的耦合比较严重,而现在 Google 通过 HIDL 这个进程通信机制将他们分隔成两个进程,这使得 Service 与 HAL 之间的通路建立过程变得复杂了一些。 
本文对 Android O 上,这两个进程的启动与初始化流程进行了简单的分析。总体来说是如下逻辑顺序:

  1. android.hardware.camera.provider@2.4-service 进程启动,仅注册 Provider;
  2. cameraserver 进程启动,实例化 CameraService,并注册到 ServiceManager 中;
  3. 由于强指针首次引用,CameraService::onFirstRef() 被调用,相当于进行初始化;
  4. 在 CameraService 初始化过程中,通过 CameraProviderManager 来获取已注册的 Provider,并实例化、初始化 CameraProvider;
  5. CameraProvider 初始化过程中,从动态库中加载了 HAL 层的关键结构,并将其封装到 CameraModule 中;
  6. 将获取到的 CameraProvider 保存在 ProviderInfo 中,以便后续的使用。

这其实就相当于 Android N 之前,整个 cameraserver 的启动流程。殊途同归,最后都是通过 CameraModule 及其内部的 camera_module_t 连接到 Camera HAL。
 

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值