CameraProvider啟動流程分析

CameraProvider進程中hidl文件

HIDL文件 服務(wù)端 客戶端 BinderName
ICameraProvider.hidl CameraProvider進程(CameraProvider.cpp) CameraService進程中使用(CameraProviderManager:: ProviderInfo) legacy/0
ICameraDevice.hidl CameraProvder進程中(CameraDevice.cpp) CameraService進程中使用 匿名Binder
ICameraDeviceCallback.hal CameraService進程 CameraProvider進程中CameraDevice.cpp在open()函數(shù)中作為參數(shù)傳遞進來 進程間的回調(diào)
ICameraDeviceSession.hal CameraProvider進程 CameraDeviceSession.cpp 在CameraService進程打開攝像頭流程中CameraProviderManager::openSession獲取 匿名Binder
type.hal CameraProvider進程

CameraProvider進程啟動時序圖

CameraProvider 啟動時序圖.png

CameraProvider 進程類圖(后續(xù)會更新)

CameraProvider進程類圖.png

CameraProvider進程的啟動流程

1、CameraProvider是Camera的Hal層程序(android.hardware.camera.provider@2.4-service )。這是一個獨立的進程,它在系統(tǒng)啟動的時候就會啟動。它通過HIDL機制來和native層的CameraService進程進行通信。
它的啟動由rc文件控制

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

1.程序的入口Service.cpp

#define LOG_TAG "android.hardware.camera.provider@2.4-service"

#include <android/hardware/camera/provider/2.4/ICameraProvider.h>
#include <hidl/LegacySupport.h>

#include <binder/ProcessState.h>

using android::hardware::camera::provider::V2_4::ICameraProvider;
using android::hardware::defaultPassthroughServiceImplementation;

int main()
{
    ALOGI("Camera provider Service is starting.");
    // The camera HAL may communicate to other vendor components via
    // /dev/vndbinder
    android::ProcessState::initWithDriver("/dev/vndbinder");
    // 在LegacySupport.h中defaultPassthroughServiceImplementation為模板類函數(shù),將會通過 sp<ICameraProvider> service = 
    // ICameraProvider::getService(name, true /* getStub */) 獲取 CameraProvider 實例化對象,以上操作,將會進入 CameraProviderAll.cpp。
    return defaultPassthroughServiceImplementation<ICameraProvider>("legacy/0", /*maxThreads*/ 6);
}

這里ICameraProvider.hal 會生成 ICameraProvider.h BpHwCameraProvider.h BnHwCameraProvider.h以及CameraProviderAll.cpp文件。 其中CameraProviderAll.cpp是上面上個頭文件的具體內(nèi)容。
然后這里的defaultPassthroughServiceImplementation()是模板函數(shù),會調(diào)用到CameraProviderAll.cpp里面(這里使用的是HIDL直通式,所以會調(diào)用到ICameraProvider對應(yīng)的CameraProviderALL.cpp中的getService()中,這個相當(dāng)于是一種固定模式

#CameraProviderAll.cpp:

//這里傳遞過來的  serviceName--"legacy/0"   getStub--true (defaultPassthroughServiceImplementation()過來的流程)
::android::sp<ICameraProvider> ICameraProvider::getService(const std::string &serviceName, const bool getStub) {
    return ::android::hardware::details::getServiceInternal<BpHwCameraProvider>(serviceName, true, getStub);
}


-------------------------------------------------------------------------------------------------------------------------------
#  system/libhidl/transport/include/hidl/HidlTransportSupport.h

template <typename BpType, typename IType = typename BpType::Pure,
          typename = std::enable_if_t<std::is_same<i_tag, typename IType::_hidl_tag>::value>,
          typename = std::enable_if_t<std::is_same<bphw_tag, typename BpType::_hidl_tag>::value>>
// instatnce  這里是傳遞來的 "legacy/0"  或者 "external/0"  retry--true getStub--false
sp<IType> getServiceInternal(const std::string& instance, bool retry, bool getStub) {
    using ::android::hidl::base::V1_0::IBase;
    //IType::descriptor --- ICameraProvider::descriptor("android.hardware.camera.provider@2.4::ICameraProvider")
    sp<IBase> base = getRawServiceInternal(IType::descriptor, instance, retry, getStub);
    if (base == nullptr) {
        return nullptr;
    }
    if (base->isRemote()) {
        // getRawServiceInternal guarantees we get the proper class
        return sp<IType>(new BpType(toBinder<IBase>(base)));
    }
    return IType::castFrom(base);
}

---------------------------------------------------------------------------------------------------------------------------------------------
#  system/libhidl/transport/Servicemanagement.cpp

sp<::android::hidl::base::V1_0::IBase> getRawServiceInternal(const std::string& descriptor,const std::string& instance, bool retry, bool getStub) {
    using Transport = ::android::hidl::manager::V1_0::IServiceManager::Transport;
    using ::android::hidl::base::V1_0::IBase;
    using ::android::hidl::manager::V1_0::IServiceManager;
    sp<Waiter> waiter;
    // 獲取 hwservicemanager 服務(wù), 用于獲取Service的client端即BpXXX代理類
    const sp<IServiceManager1_1> sm = defaultServiceManager1_1();
    if (sm == nullptr) {
        ALOGE("getService: defaultServiceManager() is null");
        return nullptr;
    }
    Return<Transport> transportRet = sm->getTransport(descriptor, instance);
    if (!transportRet.isOk()) {
        ALOGE("getService: defaultServiceManager()->getTransport returns %s", transportRet.description().c_str());
        return nullptr;
    }
    Transport transport = transportRet;
    const bool vintfHwbinder = (transport == Transport::HWBINDER);
    const bool vintfPassthru = (transport == Transport::PASSTHROUGH);
   
    、、、、、、   
   //此處省略的部分代碼 主要是 getStub為false的情況 因為CameraProvider的啟動流程中的getStub的值為true所以暫不分析

    if (getStub || vintfPassthru || vintfLegacy) {
        const sp<IServiceManager> pm = getPassthroughServiceManager();  //獲取HIDL直通式服務(wù)管理對象
        if (pm != nullptr) {
            sp<IBase> base = pm->get(descriptor, instance).withDefault(nullptr); //然后調(diào)用到了該服務(wù)對象中的get函數(shù)
            if (!getStub || trebleTestingOverride) {
                base = wrapPassthrough(base);
            }
            return base;
        }
    }
    return nullptr;
}

--------------------------------------------------------------------------------------------------------------------------------------------
#  上面的pm->get(descriptor, instance)會調(diào)用到如下函數(shù)
#  system/libhidl/transport/Servicemanagement.cpp

//這里的fqName--android.hardware.camera.provider@2.4::ICameraProvider   name-- legacy/0
Return<sp<IBase>> get(const hidl_string& fqName,const hidl_string& name) override {
        sp<IBase> ret = nullptr;
        //此處為Lambda表達式,簡單理解為函數(shù)指針即可,先執(zhí)行 openLibs() 其中第一個參數(shù)就是fqName,第二個參數(shù)是回調(diào)函數(shù)。
        // 回調(diào)函數(shù)中的  handle--dlopen()的返回值   lib--android.hardware.camera.provider@2.4-impl.so  sym--HIDL_FETCH_ICameraProvider
        openLibs(fqName, [&](void* handle, const std::string &lib, const std::string &sym) {
            //下面是回調(diào)函數(shù)的內(nèi)部邏輯
            // 聲明一個函數(shù)
            IBase* (*generator)(const char* name);
            //返回 HIDL_FETCH_ICameraProvider() 函數(shù)對應(yīng)的函數(shù)地址作為上面聲明的函數(shù)的具體內(nèi)容
            *(void **)(&generator) = dlsym(handle, sym.c_str());
            if(!generator) {
                const char* error = dlerror();
                LOG(ERROR) << "Passthrough lookup opened " << lib<< " but could not find symbol " << sym << ": "<< (error == nullptr ? "unknown error" : error);
                dlclose(handle);
                return true;
            }
            // 執(zhí)行HIDL_FETCH_ICameraProvider()函數(shù) ret作為返回值 其中ret為ICameraProvider對象
            ret = (*generator)(name.c_str());
            if (ret == nullptr) {
                dlclose(handle);
                return true; // this module doesn't provide this instance name
            }
            // Actual fqname might be a subclass.
            // This assumption is tested in vts_treble_vintf_test
            using ::android::hardware::details::getDescriptor;
            std::string actualFqName = getDescriptor(ret.get());
            CHECK(actualFqName.size() > 0);
            registerReference(actualFqName, name);  //進行服務(wù)端的注冊,這一塊暫時不做深入解析
            return false;
        });
        return ret;
    }

2、HIDL直通式后會進入到CameraProvider.cpp里面
上面HIDL相關(guān)的代碼執(zhí)行完成后會調(diào)用到CameraProvider對象里面的HIDL_FETCH_ICameraProvider()函數(shù)。在這個函數(shù)里面的參數(shù)name 的值就是之前的程序入口處傳遞來的 "legacy/0" 。接下來我們繼續(xù)走到了CameraProvider.cpp里面看看。

ICameraProvider* HIDL_FETCH_ICameraProvider(const char* name) { //這里name  "legacy/0"
    if (strcmp(name, kLegacyProviderName) == 0) {   //kLegacyProviderName是一個值為 "legacy/0"的常量
        //調(diào)用待構(gòu)造函數(shù) 創(chuàng)建對象  構(gòu)造函數(shù)里面會調(diào)用到內(nèi)部的initialize()函數(shù)來初始化
        //并將初始化的結(jié)果保存到mInitFailed的全局變量中
        CameraProvider* provider = new CameraProvider();
        if (provider == nullptr) {
            ALOGE("%s: cannot allocate camera provider!", __FUNCTION__);
            return nullptr;
        }
       //
        if (provider->isInitFailed()) { //這里就是獲取的mInitFailed
            ALOGE("%s: camera provider init failed!", __FUNCTION__);
            delete provider;
            return nullptr;
        }
        return provider;
    } else if (strcmp(name, kExternalProviderName) == 0) {
        ExternalCameraProvider* provider = new ExternalCameraProvider();
        return provider;
    }
    ALOGE("%s: unknown instance name: %s", __FUNCTION__, name);
    return nullptr;
}

3、CameraProvider的構(gòu)造函數(shù)和初始化函數(shù)--initialize()
然后調(diào)用到了CameraProvider的構(gòu)造函數(shù),在構(gòu)造函數(shù)里面只有一句代碼: mInitFailed = initialize() 這樣就會調(diào)用到內(nèi)部的initialize()函數(shù),進行初始化,并將初始化結(jié)果存儲到全局變量mInitFailed(標(biāo)識是否已經(jīng)初始化了)。接下來我們看看initialize()函數(shù)主要是做什么:

CameraProvider::CameraProvider() :
        camera_module_callbacks_t({sCameraDeviceStatusChange,
                                   sTorchModeStatusChange}) {
    mInitFailed = initialize();
}

--------------------------------------------------------------------------------------------------------------------------------------------------
bool CameraProvider::initialize() {
    camera_module_t *rawModule;   //這里的camera_module_t 是一個結(jié)構(gòu)體,它繼承了 hw_module_t的結(jié)構(gòu)體。這里就是硬件抽象的基本形式了。
    //加載對應(yīng)的so庫(camera.default.so) 給camera_module_t對象賦值
    int err = hw_get_module(CAMERA_HARDWARE_MODULE_ID,(const hw_module_t **)&rawModule);
    if (err < 0) {
        ALOGE("Could not load camera HAL module: %d (%s)", err, strerror(-err));
        return true;
    }
    // rawModule 將指向 HAL 中的 camera_module_t 類型結(jié)構(gòu)體
    //  此時,CameraProvider 與 camera HAL 綁定成功,可以通過CameraProvider操作camera HAL
    // 創(chuàng)建了一個CameraModule.cpp:android/hardware/interfaces/camera/common/1.0/default對象
    // 并將該對象賦值給全局變量mModule保存起來(這里provider調(diào)用mModule對象然后調(diào)用到CameraModule
    // 內(nèi)部的camera_module_t來操作cameraHAL)
    mModule = new CameraModule(rawModule);
    // init()里面會調(diào)用 cameraHAL的init()函數(shù),然后會獲取camera number 并存放在CameraModule中的mCameraInfoMap 里面
    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());
    // Setup vendor tags here so HAL can setup vendor keys in camera characteristics
    VendorTagDescriptor::clearGlobalVendorTagDescriptor();
    if (!setUpVendorTags()) {
        ALOGE("%s: Vendor tag setup failed, will not be available.", __FUNCTION__);
    }
    // 這里是設(shè)置camera_module_callbacks_t的回調(diào),會在當(dāng)前對象接收這些回調(diào)傳遞的數(shù)據(jù)
    err = mModule->setCallbacks(this);
    if (err != OK) {
        ALOGE("Could not set camera module callback: %d (%s)", err, strerror(-err));
        mModule.clear();
        return true;
    }
    // 從系統(tǒng)屬性中獲取HAL3的 minor的值
    mPreferredHal3MinorVersion =property_get_int32("ro.vendor.camera.wrapper.hal3TrebleMinorVersion", 3);
    ALOGV("Preferred HAL 3 minor version is %d", mPreferredHal3MinorVersion);
    switch(mPreferredHal3MinorVersion) {
        case 2:
        case 3:
            // OK
            break;
        default:
            ALOGW("Unknown minor camera device HAL version %d in property "
                    "'camera.wrapper.hal3TrebleMinorVersion', defaulting to 3", mPreferredHal3MinorVersion);
            mPreferredHal3MinorVersion = 3;
    }
    // 獲取CameraModule中存放的攝像頭數(shù)量信息
    mNumberOfLegacyCameras = mModule->getNumberOfCameras();
    for (int i = 0; i < mNumberOfLegacyCameras; i++) {
        struct camera_info info;
        auto rc = mModule->getCameraInfo(i, &info);//獲取攝像頭的基本屬性信息
        if (rc != NO_ERROR) {
            ALOGE("%s: Camera info query failed!", __func__);
            mModule.clear();
            return true;
        }
        if (checkCameraVersion(i, info) != OK) {
            ALOGE("%s: Camera version check failed!", __func__);
            mModule.clear();
            return true;
        }
        char cameraId[kMaxCameraIdLen];
        snprintf(cameraId, sizeof(cameraId), "%d", i);
        std::string cameraIdStr(cameraId);
        mCameraStatusMap[cameraIdStr] = CAMERA_DEVICE_STATUS_PRESENT;
        addDeviceNames(i);
    }
    return false; // mInitFailed
}

CameraProvider::initialize()中首先就是會調(diào)用hw_get_module()(這里會接觸到一些Android硬件抽象化的一些基礎(chǔ)知識),最終會調(diào)用到hardware.c中的load()函數(shù)里面主要是加載so庫(這個一般是廠家提供的對攝像頭具體操作的封裝,也就是對camera_module中的一些方法的具體實現(xiàn))。
通過hw_get_module() 會得到rawModule對象(可以通過這個rawModule對攝像頭進行一些操作)。然后將rawModule傳遞到CameraModule里面保存(CameraModule::mModule)起來,然后會調(diào)用到上面的camera_module_t中的init()函數(shù)。
mModule->setCallbacks(this)會將camera_module_callbacks_t中的函數(shù)回調(diào)到當(dāng)前對象CameraProvider中
下面是涉及到的一些結(jié)構(gòu)體的代碼:

typedef struct camera_module_callbacks {
    void (*camera_device_status_change)(const struct camera_module_callbacks*,int camera_id, int new_status);
    void (*torch_mode_status_change)(const struct camera_module_callbacks*,const char* camera_id,int new_status);
} camera_module_callbacks_t;


typedef struct camera_module {
    hw_module_t common;
    int (*get_number_of_cameras)(void);
    int (*get_camera_info)(int camera_id, struct camera_info *info);
    int (*set_callbacks)(const camera_module_callbacks_t *callbacks);
    void (*get_vendor_tag_ops)(vendor_tag_ops_t* ops);
    int (*open_legacy)(const struct hw_module_t* module, const char* id,
            uint32_t halVersion, struct hw_device_t** device);
    int (*set_torch_mode)(const char* camera_id, bool enabled);
    int (*init)();
    void* reserved[5];
} camera_module_t


typedef struct camera_info {
    int facing;
    int orientation;
    uint32_t device_version;
    const camera_metadata_t *static_camera_characteristics;
    int resource_cost; //當(dāng)前攝像頭使用所消耗的資源
    char** conflicting_devices;  //標(biāo)識當(dāng)前的攝像頭和那些攝像頭沖突
    size_t conflicting_devices_length;
} camera_info_t;

4、mModule->getCameraInfo(i, &info)獲取所有攝像頭的基本信息并保存在本地
接下來會根據(jù)hal層返回的攝像頭數(shù)量遍歷獲取每個攝像頭的信息,并根據(jù)這些信息對每個攝像頭進行檢查。這個里面會調(diào)用到CameraModule::getCameraInfo(int cameraId, struct camera_info *info) ,在CameraModule中主要是通過前面的camera_module_t中的get_camera_info()函數(shù)獲取攝像頭信息最后將攝像頭信息保存到 CameraModule::mCameraInfoMap

int CameraModule::getCameraInfo(int cameraId, struct camera_info *info) {
    ATRACE_CALL();
    Mutex::Autolock lock(mCameraInfoLock);
    if (cameraId < 0) {
        ALOGE("%s: Invalid camera ID %d", __FUNCTION__, cameraId);
        return -EINVAL;
    }
    // 獲取攝像頭信息 如果是API 2.0以前的就不保存
    int apiVersion = mModule->common.module_api_version;
    if (apiVersion < CAMERA_MODULE_API_VERSION_2_0) {
        int ret;
        ATRACE_BEGIN("camera_module->get_camera_info");
        ret = mModule->get_camera_info(cameraId, info);
        // Fill in this so CameraService won't be confused by
        // possibly 0 device_version
        info->device_version = CAMERA_DEVICE_API_VERSION_1_0;
        ATRACE_END();
        return ret;
    }
    //API是2.0以及之后的就需要將攝像頭信息保存起來
    ssize_t index = mCameraInfoMap.indexOfKey(cameraId);
    if (index == NAME_NOT_FOUND) {
        // Get camera info from raw module and cache it
        camera_info rawInfo, cameraInfo;
        ATRACE_BEGIN("camera_module->get_camera_info");
        int ret = mModule->get_camera_info(cameraId, &rawInfo);
        ATRACE_END();
        if (ret != 0) {
            return ret;
        }
        int deviceVersion = rawInfo.device_version;
        if (deviceVersion < CAMERA_DEVICE_API_VERSION_3_0) {
            // static_camera_characteristics is invalid
            *info = rawInfo;
            return ret;
        }
        CameraMetadata m;
        m.append(rawInfo.static_camera_characteristics);
        deriveCameraCharacteristicsKeys(rawInfo.device_version, m);
        cameraInfo = rawInfo;
        cameraInfo.static_camera_characteristics = m.release();
        index = mCameraInfoMap.add(cameraId, cameraInfo);
    }
    assert(index != NAME_NOT_FOUND);
    // return the cached camera info
    *info = mCameraInfoMap[index]; //將攝像頭信息返回上個流程的函數(shù)進行檢查
    return OK;
}

5、addDeviceNames(i) 添加攝像頭設(shè)備到本地
繼續(xù)CameraProvider::init()函數(shù)中的流程的最后一步 addDeviceName(i)。這個會執(zhí)行到當(dāng)前對象的
addDeviceNames(int camera_id, CameraDeviceStatus status = CameraDeviceStatus::PRESENT,bool cam_new = false)函數(shù)中:

/status的默認(rèn)值CameraDeviceStatus::PRESENT  cam_new的默認(rèn)值false
void CameraProvider::addDeviceNames(int camera_id, CameraDeviceStatus status, bool cam_new)
{
    char cameraId[kMaxCameraIdLen];
    snprintf(cameraId, sizeof(cameraId), "%d", camera_id);
    std::string cameraIdStr(cameraId);

    mCameraIds.add(cameraIdStr);   //將camera_id 添加到全局的mCameraIds列表中

     //給 mCameraDeviceNames 和 mOpenLegacySupported 這兩個集合賦值
    mOpenLegacySupported[cameraIdStr] = false;
    int deviceVersion = mModule->getDeviceVersion(camera_id);
    // pair可以將兩個值視為一個單元。容器類別map和multimap就是使用pairs來管理其健值/實值(key/value)的成對元素??梢詤⒖糐ava中的實體Bean理解
    // 無需寫出型別, 就可以生成一個pair對象 這里的就是std::pair<std::string, std::string>
    auto deviceNamePair = std::make_pair(cameraIdStr, getHidlDeviceName(cameraIdStr, deviceVersion));
    mCameraDeviceNames.add(deviceNamePair);
    if (cam_new) {
        mCallbacks->cameraDeviceStatusChange(deviceNamePair.second, status);
    }
    if (deviceVersion >= CAMERA_DEVICE_API_VERSION_3_2 &&
            mModule->isOpenLegacyDefined()) {
        // try open_legacy to see if it actually works
        struct hw_device_t* halDev = nullptr;
        int ret = mModule->openLegacy(cameraId, CAMERA_DEVICE_API_VERSION_1_0, &halDev);
        if (ret == 0) {
            mOpenLegacySupported[cameraIdStr] = true;
            halDev->close(halDev);
            deviceNamePair = std::make_pair(cameraIdStr,
                            getHidlDeviceName(cameraIdStr, CAMERA_DEVICE_API_VERSION_1_0));
            mCameraDeviceNames.add(deviceNamePair);
            if (cam_new) {
                mCallbacks->cameraDeviceStatusChange(deviceNamePair.second, status);
            }
        } else if (ret == -EBUSY || ret == -EUSERS) {
            // Looks like this provider instance is not initialized during
            // system startup and there are other camera users already.
            // Not a good sign but not fatal.
            ALOGW("%s: open_legacy try failed!", __FUNCTION__);
        }
    }
}

這個函數(shù)主要就是給下面的三個集合賦值
mCameraIds :SortedVector<std::string> 存儲的是攝像頭的ID 如 : "1" "2"
mCameraDeviceNames :SortedVector<std::pair<std::string, std::string>> 存儲的是一個 (cameraId string, hidl device name) pairs 對應(yīng)ID的攝像頭的設(shè)備名稱
mOpenLegacySupported : std::map<std::string, bool> 存儲的是對應(yīng)ID的攝像頭是否支持 HAL1.0(也就是老版本API)

總結(jié):

整體流程就是這樣的。
service.cpp ---> ICameraProvider.cpp --> CameraProviderAll.cpp --> HidlTransportSupport.h --> Servicemanagement.cpp --> CameraProvider.cpp --> CameraModule -->CameraHAL.so
發(fā)現(xiàn)CameraProvider進程主要有兩個作用1、給CameraService進程接口以及主動回調(diào)信息給CameraService進程。2、加載廠商提供的CameraHAL的so庫,然后獲取攝像頭信息和操作攝像頭。
和CameraService進程通信
所以CameraProvider進程主要是使用了HIDL直通式的當(dāng)時注冊了ICameraProvider.hal中的服務(wù)端,這個是用來給CameraService進程來主動調(diào)用的。然后這ICameraProvider.hal里面會有setCallback的函數(shù)主要是通過回調(diào)的形式讓CameraService進程接收CameraProvider進程主動發(fā)送的消息。
加載CameraHAL的so庫
在初始化的時候就通過hw_module_get() 加載對應(yīng)的so庫,獲取到camera_module_t對象之后賦值給CameraModule,然后在CameraModule中通過camera_module_t獲取攝像頭的信息以及后續(xù)對攝像頭進行操作。

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
平臺聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點,簡書系信息發(fā)布平臺,僅提供信息存儲服務(wù)。

推薦閱讀更多精彩內(nèi)容