第9讲 cameraserver进程启动之HIDL CameraProvider初始化 - Android C

2024年11月01日 第9讲 cameraserver进程启动之HIDL CameraProvider初始化 极客笔记

本讲是Android Camera Native Framework专题的第9讲,我们介绍cameraserver进程启动之HIDL CameraProvider初始化。

更多资源:

资源 描述
在线课程 极客笔记在线课程
知识星球 星球名称:深入浅出Android Camera 星球ID: 17296815
Wechat 极客笔记圈

HIDL Camera Provider初始化

HIDL Camera Provider初始化流程如下:

initializeHidlProvider详解

代码基于Android 13:

status_t HidlProviderInfo::initializeHidlProvider(
        sp& interface,
        int64_t currentDeviceState) {
    status_t res = parseProviderName(mProviderName, &mType, &mId);
    if (res != OK) {
        ALOGE("%s: Invalid provider name, ignoring", __FUNCTION__);
        return BAD_VALUE;
    }
    ALOGI("Connecting to new camera provider: %s, isRemote? %d",
            mProviderName.c_str(), interface->isRemote());

    // Determine minor version
    mMinorVersion = 4;
    auto cast2_6 = provider::V2_6::ICameraProvider::castFrom(interface);
    sp interface2_6 = nullptr;
    if (cast2_6.isOk()) {
        interface2_6 = cast2_6;
        if (interface2_6 != nullptr) {
            mMinorVersion = 6;
        }
    }
    // We need to check again since cast2_6.isOk() succeeds even if the provider
    // version isn't actually 2.6.
    if (interface2_6 == nullptr){
        auto cast2_5 =
                provider::V2_5::ICameraProvider::castFrom(interface);
        sp interface2_5 = nullptr;
        if (cast2_5.isOk()) {
            interface2_5 = cast2_5;
            if (interface != nullptr) {
                mMinorVersion = 5;
            }
        }
    } else {
        auto cast2_7 = provider::V2_7::ICameraProvider::castFrom(interface);
        if (cast2_7.isOk()) {
            sp interface2_7 = cast2_7;
            if (interface2_7 != nullptr) {
                mMinorVersion = 7;
            }
        }
    }

    // cameraDeviceStatusChange callbacks may be called (and causing new devices added)
    // before setCallback returns
    hardware::Return status = interface->setCallback(this);
    if (!status.isOk()) {
        ALOGE("%s: Transaction error setting up callbacks with camera provider '%s': %s",
                __FUNCTION__, mProviderName.c_str(), status.description().c_str());
        return DEAD_OBJECT;
    }
    if (status != Status::OK) {
        ALOGE("%s: Unable to register callbacks with camera provider '%s'",
                __FUNCTION__, mProviderName.c_str());
        return mapToStatusT(status);
    }

    hardware::Return linked = interface->linkToDeath(this, /*cookie*/ mId);
    if (!linked.isOk()) {
        ALOGE("%s: Transaction error in linking to camera provider '%s' death: %s",
                __FUNCTION__, mProviderName.c_str(), linked.description().c_str());
        return DEAD_OBJECT;
    } else if (!linked) {
        ALOGW("%s: Unable to link to provider '%s' death notifications",
                __FUNCTION__, mProviderName.c_str());
    }

    if (!kEnableLazyHal) {
        // Save HAL reference indefinitely
        mSavedInterface = interface;
    } else {
        mActiveInterface = interface;
    }

    ALOGV("%s: Setting device state for %s: 0x%" PRIx64,
            __FUNCTION__, mProviderName.c_str(), mDeviceState);
    notifyDeviceStateChange(currentDeviceState);

    res = setUpVendorTags();
    if (res != OK) {
        ALOGE("%s: Unable to set up vendor tags from provider '%s'",
                __FUNCTION__, mProviderName.c_str());
        return res;
    }

    // Get initial list of camera devices, if any
    std::vector devices;
    hardware::Return ret = interface->getCameraIdList([&status, this, &devices](
            Status idStatus,
            const hardware::hidl_vec& cameraDeviceNames) {
        status = idStatus;
        if (status == Status::OK) {
            for (auto& name : cameraDeviceNames) {
                uint16_t major, minor;
                std::string type, id;
                status_t res = parseDeviceName(name, &major, &minor, &type, &id);
                if (res != OK) {
                    ALOGE("%s: Error parsing deviceName: %s: %d", __FUNCTION__, name.c_str(), res);
                    status = Status::INTERNAL_ERROR;
                } else {
                    devices.push_back(name);
                    mProviderPublicCameraIds.push_back(id);
                }
            }
        } });
    if (!ret.isOk()) {
        ALOGE("%s: Transaction error in getting camera ID list from provider '%s': %s",
                __FUNCTION__, mProviderName.c_str(), linked.description().c_str());
        return DEAD_OBJECT;
    }
    if (status != Status::OK) {
        ALOGE("%s: Unable to query for camera devices from provider '%s'",
                __FUNCTION__, mProviderName.c_str());
        return mapToStatusT(status);
    }

    // Get list of concurrent streaming camera device combinations
    if (mMinorVersion >= 6) {
        res = getConcurrentCameraIdsInternalLocked(interface2_6);
        if (res != OK) {
            return res;
        }
    }

    ret = interface->isSetTorchModeSupported(
        [this](auto status, bool supported) {
            if (status == Status::OK) {
                mSetTorchModeSupported = supported;
            }
        });
    if (!ret.isOk()) {
        ALOGE("%s: Transaction error checking torch mode support '%s': %s",
                __FUNCTION__, mProviderName.c_str(), ret.description().c_str());
        return DEAD_OBJECT;
    }

    mIsRemote = interface->isRemote();

    initializeProviderInfoCommon(devices);

    return OK;
}

解释:

  1. 通过castFrom来判断ICameraProvider的mMinorVersion
  2. 调用setCallback方法,接收ICameraProviderCallback的回调
  3. 调用linkToDeath方法,在serviceDied处理HAL进程挂掉后的异常,remove掉Provider
  4. 调用notifyDeviceStateChange通知Camera HAL进程,当前摄像头的状态(NORMAL/BACK_COVERED/FRONT_COVERED/FOLDED,可以一次性通知多个状态),该功能在Provider 2.5及之后的版本才有
  5. setUpVendorTags,调用ICameraProvider的getVendorTags方法拿到VendorTagSection,然后创建VendorTagDescriptor,通过VendorTagDescriptor就能知道有哪些Vendor Tag了
  6. 调用ICameraProvider的getCameraIdList方法获取到当前Provider支持的Camera Device,解析出Camera ID存放在mProviderPublicCameraIds(解析规则解读)
  7. 针对Provider >= 2.6

    • 调用Provider的getConcurrentStreamingCameraIds获取哪些Camera可以同时做ConfigureStream,存放在mConcurrentCameraIdCombinations
  8. 调用Provider的isSetTorchModeSupported判断是否支持手电筒,存放在mSetTorchModeSupported
  9. 调用initializeProviderInfoCommon,完成Device的初始化

本文链接:http://so.lmcjl.com/news/16755/

展开阅读全文