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 進程類圖(后續(xù)會更新)
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ù)對攝像頭進行操作。