第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<provider::V2_4::ICameraProvider>& 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&lt;provider::V2_6::ICameraProvider&gt; 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&#039;t actually 2.6.
if (interface2_6 == nullptr){
    auto cast2_5 =
            provider::V2_5::ICameraProvider::castFrom(interface);
    sp&lt;provider::V2_5::ICameraProvider&gt; 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&lt;provider::V2_7::ICameraProvider&gt; 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&lt;Status&gt; status = interface-&gt;setCallback(this);
if (!status.isOk()) {
    ALOGE(&quot;%s: Transaction error setting up callbacks with camera provider &#039;%s&#039;: %s&quot;,
            __FUNCTION__, mProviderName.c_str(), status.description().c_str());
    return DEAD_OBJECT;
}
if (status != Status::OK) {
    ALOGE(&quot;%s: Unable to register callbacks with camera provider &#039;%s&#039;&quot;,
            __FUNCTION__, mProviderName.c_str());
    return mapToStatusT(status);
}

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

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

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

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

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

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

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

mIsRemote = interface-&gt;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的初始化