[Android O] HAL3 之 Open Camera2 流程(二)—— 从 CameraService 到 HAL Service

之前已经分析了从 App 到 CameraService 的连路创建流程,接下来要分析的是从 CameraService 到 HAL Service 的连接过程。

由于 Android O 中加入了 Treble 机制,它带来的一个巨大变化就是将原本的 CameraServer 进程分隔成 CameraServerProvider service 两个进程,它们之间通过 HIDL(一个类似 Binder 的机制)进行通信。
在这种情况下,CameraServer 一端主体为 CameraService,它将会寻找现存的 Provider service,将其加入到内部的 CameraProviderManager 中进行管理,相关操作都是通过远端调用进行的。
Provider service 一端的主体为 CameraProvider,它在初始化时就已经连接到 libhardware 的 Camera HAL 实现层,并以 CameraModule 来进行管理。

这两个进程的启动与初始化是在系统启动时就进行的,相关的分析可以参照我的另一篇博文
进程的启动后,连路的 “载体” 就搭建完成了(需要注意,此时 QCamera3HWI 还未创建),可用下图简单表示。
(我之前的博文中没有分析远端 CameraDevice 的创建,但这个类确实需要注意,因为它是连接到 HAL 接口层的中介。)
@图. CS 到 HAL 的连路载体

而在打开相机时,该层的完整连路会被创建出来。

这一部分的主要调用逻辑如下图。
@图. CS 到 HAL 打开相机调用流程

上回讲到,在 CameraService::makeClient 中,实例化了一个 CameraDeviceClient。现在我们就从它的构造函数开始,继续探索打开相机的流程。

这一部分主要活动在 Runtime 层,这里分成 CameraService 与 HAL Service 两侧来分析。

CS

CameraDeviceClient

文件路径:frameworks\av\services\camera\libcameraservice\api2\CameraDeviceClient.cpp

先来看看它的构造函数,主要注意第 9、10 行,关于它的父类 Camera2ClientBase 的构造,这是创建连路的一个关键节点。在下一个小节会对它进行分析。

CameraDeviceClient::CameraDeviceClient(const sp<CameraService>& cameraService,
        const sp<hardware::camera2::ICameraDeviceCallbacks>& remoteCallback,
        const String16& clientPackageName,
        const String8& cameraId,
        int cameraFacing,
        int clientPid,
        uid_t clientUid,
        int servicePid) :
    Camera2ClientBase(cameraService, remoteCallback, clientPackageName,
                cameraId, cameraFacing, clientPid, clientUid, servicePid),
    mInputStream(),
    mStreamingRequestId(REQUEST_ID_NONE),
    mRequestIdCounter(0),
    mPrivilegedClient(false) {

    char value[PROPERTY_VALUE_MAX];
    property_get("persist.camera.privapp.list", value, "");
    String16 packagelist(value);
    if (packagelist.contains(clientPackageName.string())) {
        mPrivilegedClient = true;
    }

    ATRACE_CALL();
    ALOGI("CameraDeviceClient %s: Opened", cameraId.string());
}

CameraService 在创建 CameraDeviceClient 之后,会调用它的初始化函数:

  • 第 1~3 行,即是对外提供调用的初始化函数接口 initialize
  • 第 5、6 行,初始化的具体实现函数,模板 TProviderPtr 在此处即是 CameraProviderManager 类。
  • 第 10 行,首先将父类初始化,注意此处传入了 CameraProviderManager。
  • 第 15~23 行,这里是关于 FrameProcessor 的创建与初始化配置等等,这个东西可能是用于处理上传的每帧数据的,暂时不深入分析。
status_t CameraDeviceClient::initialize(sp<CameraProviderManager> manager) {
    return initializeImpl(manager);
}

template<typename TProviderPtr>
status_t CameraDeviceClient::initializeImpl(TProviderPtr providerPtr) {
    ATRACE_CALL();
    status_t res;

    res = Camera2ClientBase::initialize(providerPtr);
    if (res != OK) {
        return res;
    }

    String8 threadName;
    mFrameProcessor = new FrameProcessorBase(mDevice);
    threadName = String8::format("CDU-%s-FrameProc", mCameraIdStr.string());
    mFrameProcessor->run(threadName.string());

    mFrameProcessor->registerListener(FRAME_PROCESSOR_LISTENER_MIN_ID,
                                      FRAME_PROCESSOR_LISTENER_MAX_ID,
                                      /*listener*/this,
                                      /*sendPartials*/true);

    return OK;
}

Camera2ClientBase

文件路径:frameworks\av\services\camera\libcameraservice\common\Camera2ClientBase.cpp

先来看构造函数:

  • 第 1 行,这个模板 TClientBase,在 CameraDeviceClient 继承 Camera2ClientBase 时被指定为 CameraDeviceClientBase
  • 第 2~15 行,构造的相关参数,以及初始化列表,这里面需要注意 TCamCallbacks 在 CameraDeviceClientBase 中被指定为了 ICameraDeviceCallbacks
  • 第 21 行则是一个关键点,创建了一个 Camera3Device
template <typename TClientBase>
Camera2ClientBase<TClientBase>::Camera2ClientBase(
        const sp<CameraService>& cameraService,
        const sp<TCamCallbacks>& remoteCallback,
        const String16& clientPackageName,
        const String8& cameraId,
        int cameraFacing,
        int clientPid,
        uid_t clientUid,
        int servicePid):
        TClientBase(cameraService, remoteCallback, clientPackageName,
                cameraId, cameraFacing, clientPid, clientUid, servicePid),
        mSharedCameraCallbacks(remoteCallback),
        mDeviceVersion(cameraService->getDeviceVersion(TClientBase::mCameraIdStr)),
        mDeviceActive(false)
{
    ALOGI("Camera %s: Opened. Client: %s (PID %d, UID %d)", cameraId.string(),
            String8(clientPackageName).string(), clientPid, clientUid);

    mInitialClientPid = clientPid;
    mDevice = new Camera3Device(cameraId);
    LOG_ALWAYS_FATAL_IF(mDevice == 0, "Device should never be NULL here.");
}

再来看看初始化函数:

  • 第 1~4 行,初始化函数接口,真正的实现部分在 initializeImpl 中。
  • 第 6、7 行,注意此处,TClientBase 对应 CameraDeviceClientBase,而 TProviderPtr 对应的是 CameraProviderManager
  • 第 14~18 行,调用 CameraDeviceClientBase 的 startCameraOps 方法,检查 ops 的权限。
  • 第 26 行,初始化 Camera3Device 的实例,注意此处传入了 CameraProviderManager。
  • 第 33、34 行,在 Camera3Device 实例中设置 Notify 回调。
template <typename TClientBase>
status_t Camera2ClientBase<TClientBase>::initialize(sp<CameraProviderManager> manager) {
    return initializeImpl(manager);
}

template <typename TClientBase>
template <typename TProviderPtr>
status_t Camera2ClientBase<TClientBase>::initializeImpl(TProviderPtr providerPtr) {
    ATRACE_CALL();
    ALOGV("%s: Initializing client for camera %s", __FUNCTION__,
          TClientBase::mCameraIdStr.string());
    status_t res;

    // Verify ops permissions
    res = TClientBase::startCameraOps();
    if (res != OK) {
        return res;
    }

    if (mDevice == NULL) {
        ALOGE("%s: Camera %s: No device connected",
                __FUNCTION__, TClientBase::mCameraIdStr.string());
        return NO_INIT;
    }

    res = mDevice->initialize(providerPtr);
    if (res != OK) {
        ALOGE("%s: Camera %s: unable to initialize device: %s (%d)",
                __FUNCTION__, TClientBase::mCameraIdStr.string(), strerror(-res), res);
        return res;
    }

    wp<CameraDeviceBase::NotificationListener> weakThis(this);
    res = mDevice->setNotifyCallback(weakThis);

    return OK;
}

Camera3Device

文件路径:frameworks\av\services\camera\libcameraservice\device3\Camera3Device.cpp

观察构造函数,注意第 18、19 行设定了两个回调接口。

Camera3Device::Camera3Device(const String8 &id):
        mId(id),
        mOperatingMode(NO_MODE),
        mIsConstrainedHighSpeedConfiguration(false),
        mStatus(STATUS_UNINITIALIZED),
        mStatusWaiters(0),
        mUsePartialResult(false),
        mNumPartialResults(1),
        mTimestampOffset(0),
        mNextResultFrameNumber(0),
        mNextReprocessResultFrameNumber(0),
        mNextShutterFrameNumber(0),
        mNextReprocessShutterFrameNumber(0),
        mListener(NULL),
        mVendorTagId(CAMERA_METADATA_INVALID_VENDOR_ID)
{
    ATRACE_CALL();
    camera3_callback_ops::notify = &sNotify;
    camera3_callback_ops::process_capture_result = &sProcessCaptureResult;
    ALOGV("%s: Created device for camera %s", __FUNCTION__, mId.string());
}

其初始化函数篇幅较长,这里省略掉了关于 RequestMetadataQueue 的相关操作。我们需要关注的是,在初始化时,调用了 CameraProviderManager 的 openSession 方法(第 13~21 行),开启了远端的 Session

status_t Camera3Device::initialize(sp<CameraProviderManager> manager) {
    ATRACE_CALL();
    Mutex::Autolock il(mInterfaceLock);
    Mutex::Autolock l(mLock);

    ALOGV("%s: Initializing HIDL device for camera %s", __FUNCTION__, mId.string());
    if (mStatus != STATUS_UNINITIALIZED) {
        CLOGE("Already initialized!");
        return INVALID_OPERATION;
    }
    if (manager == nullptr) return INVALID_OPERATION;

    sp<ICameraDeviceSession> session;
    ATRACE_BEGIN("CameraHal::openSession");
    status_t res = manager->openSession(mId.string(), this,
            /*out*/ &session);
    ATRACE_END();
    if (res != OK) {
        SET_ERR_L("Could not open camera session: %s (%d)", strerror(-res), res);
        return res;
    }

    /* Do something in */
    ......
    /* Do something out */

    return initializeCommonLocked();
}

CameraProviderManager

文件位置:frameworks\av\services\camera\libcameraservice\common\CameraProviderManager.cpp

来看看 openSession 是如何实现的:

  • 第 8~12 行,首先调用 findDeviceInfoLocked,获取 HAL3 相关的 DeviceInfo3,这个东西在服务启动与初始化的时候就已经创建出来,并保存下来了。
  • 第 16~22 行,注意此处,通过远端调用 CameraDevice 的 open 方法,创建 CameraDeviceSession 实例并将其本地调用接口通过入参 session 返回。 (DeviceInfo3 这个类的 mInterface 成员类型是 ICameraDevice,通过它可以调用远端 CameraDevice 中的方法。)
status_t CameraProviderManager::openSession(const std::string &id,
        const sp<hardware::camera::device::V3_2::ICameraDeviceCallback>& callback,
        /*out*/
        sp<hardware::camera::device::V3_2::ICameraDeviceSession> *session) {

    std::lock_guard<std::mutex> lock(mInterfaceMutex);

    auto deviceInfo = findDeviceInfoLocked(id,
            /*minVersion*/ {3,0}, /*maxVersion*/ {4,0});
    if (deviceInfo == nullptr) return NAME_NOT_FOUND;

    auto *deviceInfo3 = static_cast<ProviderInfo::DeviceInfo3*>(deviceInfo);

    Status status;
    hardware::Return<void> ret;
    ret = deviceInfo3->mInterface->open(callback, [&status, &session]
            (Status s, const sp<device::V3_2::ICameraDeviceSession>& cameraSession) {
                status = s;
                if (status == Status::OK) {
                    *session = cameraSession;
                }
            });
    if (!ret.isOk()) {
        ALOGE("%s: Transaction error opening a session for camera device %s: %s",
                __FUNCTION__, id.c_str(), ret.description().c_str());
        return DEAD_OBJECT;
    }
    return mapToStatusT(status);
}

HAL Service

CameraDevice

文件位置:hardware\interfaces\camera\device\3.2\default\CameraDevice.cpp

CameraDevice 的实例实际上在初始化 HAL Service 之后就存在了。
前面说到,通过 CameraProviderManager 中的 deviceInfo 接口,调用远端 CameraDevice 实例open 方法,下面就来看看它的代码实现:

  • 第 28 行,注意 mModule 是在 HAL Service 初始化时就已经配置好的,它对从 libhardware 库中加载的 Camera HAL 接口进行了一层封装。从这里往下就会一路走到 QCamera3HWI 的构造流程去,在这一章中暂时不进行分析。
  • 第 36、43 行,创建 session 并让内部成员 mSession 持有,具体实现的函数为 creatSession
Return<void> CameraDevice::open(const sp<ICameraDeviceCallback>& callback, open_cb _hidl_cb)  {
    Status status = initStatus();
    sp<CameraDeviceSession> session = nullptr;

    if (callback == nullptr) {
        ALOGE("%s: cannot open camera %s. callback is null!",
                __FUNCTION__, mCameraId.c_str());
        _hidl_cb(Status::ILLEGAL_ARGUMENT, nullptr);
        return Void();
    }

    if (status != Status::OK) {
        /* Do something in */
        ......
        /* Do something out */
    } else {
        mLock.lock();

        /* Do something in */
        ......
        /* Do something out */

        /** Open HAL device */
        status_t res;
        camera3_device_t *device;

        ATRACE_BEGIN("camera3->open");
        res = mModule->open(mCameraId.c_str(),
                reinterpret_cast<hw_device_t**>(&device));
        ATRACE_END();

        /* Do something in */
        ......
        /* Do something out */

        session = createSession(
                device, info.static_camera_characteristics, callback);

        /* Do something in */
        ......
        /* Do something out */

        mSession = session;

        IF_ALOGV() {
            session->getInterface()->interfaceChain([](
                ::android::hardware::hidl_vec<::android::hardware::hidl_string> interfaceChain) {
                    ALOGV("Session interface chain:");
                    for (auto iface : interfaceChain) {
                        ALOGV("  %s", iface.c_str());
                    }
                });
        }
        mLock.unlock();
    }
    _hidl_cb(status, session->getInterface());
    return Void();
}

creatSession 中的实现就非常简单了,直接创建了一个 CameraDeviceSession。当然在其构造函数中会调用内部的初始化函数,然后会进入 HAL 接口层 QCamera3HWI 的初始化流程,这里就先不分析了。
至此,从 CameraService 到 HAL Service 这一部分的打开相机流程就基本走通了。

sp<CameraDeviceSession> CameraDevice::createSession(camera3_device_t* device,
        const camera_metadata_t* deviceInfo,
        const sp<ICameraDeviceCallback>& callback) {
    return new CameraDeviceSession(device, deviceInfo, callback);
}

简图总结

根据上面的流程追踪,我们可以描绘出一个比较简单直观的连路框架图,如下。
@图. CameraService 连接到 HAL Service 示意图

猜你喜欢

转载自blog.csdn.net/qq_16775897/article/details/81661055