欢迎关注微信公众号
前言
不积跬步,无以至千里;不积小流,无以成江海。
本章将作为Android Camera系列的开篇,后续将会持续输出相关文章,尽可能的形成一个完整的系列内容。全部更新完毕时间可能会比较长,因为Camera的东西其实很多的,本人也需要不断的学习和深入。由于目前对Camera驱动的内容了解的不多,所以驱动的内容会放到最后来讲,还希望大家理解和耐心等待,如果文章中有错误或者大家有想交流的内容都可以直接跟我交流,我们一起学习!
我们会先介绍Camera相关服务的启动流程,然后再讲解Camera的业务调用流程。原因是系统开机时Camera服务会进行一系列的初始化,这样上层应用使用Camera功能时就可以节省一些时间和资源,从而加快整个Camera业务流程的效率。我们会先讲Camera HAL服务的启动流程,然后再讲解cameraserver服务的启动流程,最后从上层应用的调用流程来详细分析Camera每个业务(比如预览、拍照、录像等)的具体实现。
所以本章就从Camera HAL服务的启动流程开始,本想用一篇文章来介绍完Camera HAL启动流程的,结果越写越多,写的多了代码就不容易连贯,反而影响阅读体验,故而分为多个章节来介绍,希望能够讲透彻,讲条理,讲清楚。
Android Camera整体架构
Camera的整体架构符合标准的Android架构,即App->FWK->HAL->Kernel,只不过在Android8.0之前HAL的so库是被System分区的服务动态加载的,对于camera hal来说就是被cameraserver进程动态加载,hal和cameraserver进程属于同一个进程。在Android8.0之后,Google加入了Treble机制,将HAL放到了独立的进程当中并且位于vendor分区,System服务通过binder访问vendor分区的HAL进程。对于camera来说就是cameraserver进程通过binder访问Camera HAL进程,后者在开机时通过init启动。这样就可以将厂商的私有实现与Google发布的aosp进行隔离,在系统升级时如果厂商的vendor分区没有修改的话,就可以不升级vendor分区,但是厂商必须按照Google定义的标准接口来实现HAL。
CameraProvider
Camera HAL运行在CameraProvider进程当中,目前已经到2.7版本,但是使用最多的是2.4版本,2.4是加入Treble机制后CameraProvider进程的第一个版本,所以我们先从这里开始。
CameraProvider进程是一个native服务,通过init.rc启动
(
真正的进程名称是android.hardware.camera.provider@2.4-service_64,这里我们为了简写统一叫成CameraProvider进程
)
// hardware/interfaces/camera/provider/2.4/default/android.hardware.camera.provider@2.4-service_64.rc
service vendor.camera-provider-2-4/vendor/bin/hw/android.hardware.camera.provider@2.4-service_64
interface android.hardware.camera.provider@2.4::ICameraProvider legacy/0classhal
user cameraserver
group audio camera input drmrpc
ioprio rt 4
capabilities SYS_NICE
task_profiles CameraServiceCapacity MaxPerformance
由上可以看出,进程启动时执行的时二进制/vendor/bin/hw/android.hardware.camera.provider@2.4-service_64,下面我们从Android.bp中找到该二进制的入口文件和入口函数。
// hardware/interfaces/camera/provider/2.4/default/Android.bp...
cc_binary {
name:"android.hardware.camera.provider@2.4-service_64",
defaults:["camera_service_defaults"],
compile_multilib:"64",
init_rc:["android.hardware.camera.provider@2.4-service_64.rc"],}
cc_defaults {
name:"camera_service_defaults",
defaults:["hidl_defaults"],
proprietary:true,
relative_install_path:"hw",
srcs:["service.cpp"],// 二进制入口肯定时service.cpp里面的main函数
shared_libs:["android.hardware.camera.common@1.0","android.hardware.camera.device@1.0","android.hardware.camera.device@3.2","android.hardware.camera.device@3.3","android.hardware.camera.device@3.4","android.hardware.camera.device@3.5","android.hardware.camera.provider@2.4","android.hardware.graphics.mapper@2.0","android.hardware.graphics.mapper@3.0","android.hardware.graphics.mapper@4.0","android.hidl.allocator@1.0","android.hidl.memory@1.0","libbinder","libcamera_metadata","libcutils","libhardware","libhidlbase","liblog","libutils",],
static_libs:["android.hardware.camera.common@1.0-helper",],
header_libs:["camera.device@3.4-external-impl_headers","camera.device@3.4-impl_headers","camera.device@3.5-external-impl_headers","camera.device@3.5-impl_headers",],}...从以上Android.bp文件中可以看出,/vendor/bin/hw/android.hardware.camera.provider@2.4-service_64只包含了一个源文件service.cpp,那么入口函数肯定就是这个cpp里面的main函数了。
// hardware/interfaces/camera/provider/2.4/default/service.cppintmain(){ALOGI("CameraProvider@2.4 legacy service is starting.");// The camera HAL may communicate to other vendor components via// /dev/vndbinder// 这里表示Camera hal可以跟其他 vendor hal进程通过binder通信,否则不可以
android::ProcessState::initWithDriver("/dev/vndbinder");// b/166675194if(property_get_bool("ro.vendor.camera.provider24.disable_mem_init",false)){if(mallopt(M_BIONIC_ZERO_INIT,0)==0){// Note - heap initialization is only present on devices with Scudo.// Devices with jemalloc don't have heap-init, and thus the mallopt// will fail. On these devices, you probably just want to remove the// property.ALOGE("Disabling heap initialization failed.");}}
status_t status;if(kLazyService){
status =defaultLazyPassthroughServiceImplementation<ICameraProvider>("legacy/0",/*maxThreads*/6);}else{// kLazyService就是会延迟初始化,我们这里不细讲,后面单出一个章节介绍一下// 启动时会执行下面的函数,这里记下这里的泛型类型为ICameraProvider,还有两个参数,后面有用
status =defaultPassthroughServiceImplementation<ICameraProvider>("legacy/0",/*maxThreads*/6);}return status;}defaultPassthroughServiceImplementation的实现如下:
// system/libhidl/transport/include/hidl/LegacySupport.h// 这里的两个泛型参数都为ICameraProvidertemplate<classInterface,classExpectInterface= Interface>__attribute__((warn_unused_result)) status_t defaultPassthroughServiceImplementation(const std::string& name, size_t maxThreads =1){// 设置该进程中binder通信线程池的最大线程数,这里maxThreads=6configureRpcThreadpool(maxThreads,true);// 注意这里的泛型类型为ICameraProvider, 参数name为legacy/0
status_t result =registerPassthroughServiceImplementation<Interface, ExpectInterface>(name);if(result != OK){return result;}// 把当前线程也就是主线程加入binder线程池joinRpcThreadpool();return UNKNOWN_ERROR;}registerPassthroughServiceImplementation最终会执行到如下函数:
// system/libhidl/transport/include/hidl/LegacySupport.htemplate<classInterface,classExpectInterface= Interface>__attribute__((warn_unused_result)) status_t registerPassthroughServiceImplementation(const std::string& name ="default"){// 这里Interface和ExpectInterface是ICameraProvider// ICameraProvider::descriptor为android.hardware.camera.provider@2.4::ICameraProvider// 至于ICameraProvider::descriptor的值哪里赋值的,后面细讲returnregisterPassthroughServiceImplementation(Interface::descriptor,
ExpectInterface::descriptor, name);}// system/libhidl/transport/LegacySupport.cpp__attribute__((warn_unused_result)) status_t registerPassthroughServiceImplementation(const std::string& interfaceName,const std::string& expectInterfaceName,const std::string& serviceName){// 这里前两个参数为android.hardware.camera.provider@2.4::ICameraProvider,// 第三个参数为lambda表达式的一个函数,该函数传入两个参数,然后执行registerAsServiceInternal// 第四个参数为legacy/0return details::registerPassthroughServiceImplementation(
interfaceName, expectInterfaceName,[](const sp<IBase>& service,const std::string& name){return details::registerAsServiceInternal(service, name);},
serviceName);}// system/libhidl/transport/LegacySupport.cpp// 这个函数主要干了两件事情// 1. 打开camera hal的so库,初始化Camera Hal,比如获取camera numbers,在getRawServiceInternal里实现// 2. 将camera hal注册为binder服务,在registerServiceCb里实现,也就是上一步的lamda函数,最终调用的是// registerAsServiceInternal__attribute__((warn_unused_result)) status_t registerPassthroughServiceImplementation(const std::string& interfaceName,const std::string& expectInterfaceName,
RegisterServiceCb registerServiceCb,const std::string& serviceName){// 这是一个关键函数,第一个参数为android.hardware.camera.provider@2.4::ICameraProvider// 第二个参数为 legacy/0// 我们下面先分析这个函数,然后再继续
sp<IBase> service =getRawServiceInternal(interfaceName, serviceName,true/*retry*/,true/*getStub*/);// 这里我们把后面的代码先省略掉,等getRawServiceInternal函数讲完之后再继续往下分析...}getRawServiceInternal
// system/libhidl/transport/ServiceManagement.cpp// 第一个参数为android.hardware.camera.provider@2.4::ICameraProvider// 第二个参数为 legacy/0// 后两个参数都为true
sp<::android::hidl::base::V1_0::IBase>getRawServiceInternal(const std::string& descriptor,const std::string& instance,bool retry,bool getStub){using Transport = IServiceManager1_0::Transport;
sp<Waiter> waiter;
sp<IServiceManager1_1> sm;
Transport transport = Transport::EMPTY;if(kIsRecovery){
transport = Transport::PASSTHROUGH;}else{
sm =defaultServiceManager1_1();if(sm ==nullptr){ALOGE("getService: defaultServiceManager() is null");returnnullptr;}// 这里最终会去读取/vendor/etc/vintf/manifest.xml文件来获取当前transport类型// 初始文件在device/xxx/manifest.xml,编译时跟其他manifest// 一起写入/vendor/etc/vintf/manifest.xml,定义如下:/*
<manifest version="1.0" type="device" target-level="3">
<hal format="hidl">
<name>android.hardware.camera.provider</name>
<transport>hwbinder</transport>
<fqname>@2.4::ICameraProvider/legacy/0</fqname>
</hal>
</manifest>
*/// transport类型决定了当前HAL是绑定式还是直通式
Return<Transport> transportRet = sm->getTransport(descriptor, instance);if(!transportRet.isOk()){ALOGE("getService: defaultServiceManager()->getTransport returns %s",
transportRet.description().c_str());returnnullptr;}
transport = transportRet;}constbool vintfHwbinder =(transport == Transport::HWBINDER);// trueconstbool vintfPassthru =(transport == Transport::PASSTHROUGH);// falseconstbool trebleTestingOverride =isTrebleTestingOverride();// falseconstbool allowLegacy =!kEnforceVintfManifest ||(trebleTestingOverride &&isDebuggable());// falseconstbool vintfLegacy =(transport == Transport::EMPTY)&& allowLegacy;// falseif(!kEnforceVintfManifest){ALOGE("getService: Potential race detected. The VINTF manifest is not being enforced. If ""a HAL server has a delay in starting and it is not in the manifest, it will not be ""retrieved. Please make sure all HALs on this device are in the VINTF manifest and ""enable PRODUCT_ENFORCE_VINTF_MANIFEST on this device (this is also enabled by ""PRODUCT_FULL_TREBLE). PRODUCT_ENFORCE_VINTF_MANIFEST will ensure that no race ""condition is possible here.");sleep(1);}// 因为参数getStub为true,所以这里的for循环不进入,不执行for(int tries =0;!getStub &&(vintfHwbinder || vintfLegacy); tries++){if(waiter ==nullptr&& tries >0){
waiter =newWaiter(descriptor, instance, sm);}if(waiter !=nullptr){
waiter->reset();// don't reorder this -- see comments on reset()}
Return<sp<IBase>> ret = sm->get(descriptor, instance);if(!ret.isOk()){ALOGE("getService: defaultServiceManager()->get returns %s for %s/%s.",
ret.description().c_str(), descriptor.c_str(), instance.c_str());break;}
sp<IBase> base = ret;if(base !=nullptr){
Return<bool> canCastRet =
details::canCastInterface(base.get(), descriptor.c_str(),true/* emitError */);if(canCastRet.isOk()&& canCastRet){if(waiter !=nullptr){
waiter->done();}return base;// still needs to be wrapped by Bp class.}if(!handleCastError(canCastRet, descriptor, instance))break;}// In case of legacy or we were not asked to retry, don't.if(vintfLegacy ||!retry)break;if(waiter !=nullptr){ALOGI("getService: Trying again for %s/%s...", descriptor.c_str(), instance.c_str());
waiter->wait(true/* timeout */);}}if(waiter !=nullptr){
waiter->done();}// getStub为true,进入这里的if语句if(getStub || vintfPassthru || vintfLegacy){// getPassthroughServiceManager 返回new PassthroughServiceManager()const sp<IServiceManager1_0> pm =getPassthroughServiceManager();if(pm !=nullptr){// 下面单独分析PassthroughServiceManager的get函数
sp<IBase> base = pm->get(descriptor, instance).withDefault(nullptr);// getStub为true, trebleTestingOverride为false,这里的if进不去if(!getStub || trebleTestingOverride){
base =wrapPassthrough(base);}return base;}}returnnullptr;}PassthroughServiceManager.get
// system/libhidl/transport/ServiceManagement.cpp// descriptor: android.hardware.camera.provider@2.4::ICameraProvider// instance: legacy/0
sp<IBase> base = pm->get(descriptor, instance)
Return<sp<IBase>>get(const hidl_string& fqName,const hidl_string& name)override{
sp<IBase> ret =nullptr;// 主要就是执行了openLibs函数,我们先把参数理一下,然后在进入openLibs函数进行分析// 第一个参数fqName: android.hardware.camera.provider@2.4::ICameraProvider// 第二个参数是一个lamda函数,这个函数有三个参数,这里主要是这个lamda函数的实现,// 这里我们先省略,到调用的时候再详细讲openLibs(fqName,[&](void* handle,const std::string &lib,const std::string &sym){...}}PassthroughServiceManager.openLibs
// system/libhidl/transport/ServiceManagement.cpp// openLibs函数实现staticvoidopenLibs(// fqName: android.hardware.camera.provider@2.4::ICameraProviderconst std::string& fqName,// eachLib: 就是上面提到的lamda函数const std::function<bool/* continue */(void*/* handle */,const std::string&/* lib */,const std::string&/* sym */)>& eachLib){//fqName looks like android.hardware.foo@1.0::IFoo// 用::符号将参数分割为android.hardware.camera.provider@2.4和ICameraProvider
size_t idx = fqName.find("::");if(idx == std::string::npos ||
idx +strlen("::")+1>= fqName.size()){LOG(ERROR)<<"Invalid interface name passthrough lookup: "<< fqName;return;}// 这里拿到的就是android.hardware.camera.provider@2.4
std::string packageAndVersion = fqName.substr(0, idx);// 这里拿到的就是 ICameraProvider
std::string ifaceName = fqName.substr(idx +strlen("::"));// prefix为android.hardware.camera.provider@2.4-implconst std::string prefix = packageAndVersion +"-impl";// sym为 HIDL_FETCH_ICameraProviderconst std::string sym ="HIDL_FETCH_"+ ifaceName;// 到此,上面参数已经解析完毕,下面根据prefix和sym来执行constexprint dlMode = RTLD_LAZY;void* handle =nullptr;dlerror();// clearstatic std::string halLibPathVndkSp = details::getVndkSpHwPath();
std::vector<std::string> paths ={
HAL_LIBRARY_PATH_ODM, HAL_LIBRARY_PATH_VENDOR, halLibPathVndkSp,#ifndef__ANDROID_VNDK__
HAL_LIBRARY_PATH_SYSTEM,#endif};// 这里翻译下上面的paths变量:
std::vector<std::string> paths ={"/odm/lib64/hw/","/vendor/lib64/hw/","/apex/com.android.vndk.v33/lib64/hw/",#ifndef__ANDROID_VNDK__"/system/lib64/hw/",#endif};// 条件为false,不进入if(details::isTrebleTestingOverride()){// Load HAL implementations that are statically linked
handle =dlopen(nullptr, dlMode);if(handle ==nullptr){constchar* error =dlerror();LOG(ERROR)<<"Failed to dlopen self: "<<(error ==nullptr?"unknown error": error);}elseif(!eachLib(handle,"SELF", sym)){return;}}// 在paths的几个路径中寻找android.hardware.camera.provider@2.4-impl.so文件// 我们到设备里查看一下,发现在/vendor/lib64/hw目录下,因为是64位系统,所以/vendor/lib/hw/是不会遍历的// 130|emulator_car_x86_64:/ # find . -name android.hardware.camera.provider@2.4-impl.so // ./vendor/lib/hw/android.hardware.camera.provider@2.4-impl.so// ./vendor/lib64/hw/android.hardware.camera.provider@2.4-impl.sofor(const std::string& path : paths){
std::vector<std::string> libs =findFiles(path, prefix,".so");for(const std::string &lib : libs){// fullPath=/vendor/lib64/hw/android.hardware.camera.provider@2.4-impl.soconst std::string fullPath = path + lib;if(kIsRecovery || path == HAL_LIBRARY_PATH_SYSTEM){
handle =dlopen(fullPath.c_str(), dlMode);}else{#if!defined(__ANDROID_RECOVERY__)&&defined(__ANDROID__)// 最终执行这里,load so库,拿到handle
handle =android_load_sphal_library(fullPath.c_str(), dlMode);#endif}if(handle ==nullptr){constchar* error =dlerror();LOG(ERROR)<<"Failed to dlopen "<< lib <<": "<<(error ==nullptr?"unknown error": error);continue;}// 还记得eachLib函数吗,就是上面省略掉的lamda函数,下面开始分析if(!eachLib(handle, lib, sym)){return;}}}}下面开始讲解eachLib lamda实现
// 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;// 这里的handle为dlopen /vendor/lib64/hw/android.hardware.camera.provider@2.4-impl.so后的handle// lib参数为android.hardware.camera.provider@2.4-impl.so// sym参数为HIDL_FETCH_ICameraProvideropenLibs(fqName,[&](void* handle,const std::string &lib,const std::string &sym){
IBase*(*generator)(constchar* name);// 通过dlsym在android.hardware.camera.provider@2.4-impl.so中找到HIDL_FETCH_ICameraProvider的地址*(void**)(&generator)=dlsym(handle, sym.c_str());if(!generator){constchar* error =dlerror();LOG(ERROR)<<"Passthrough lookup opened "<< lib <<" but could not find symbol "<< sym <<": "<<(error ==nullptr?"unknown error": error)<<". Keeping library open.";// dlclose too problematic in multi-threaded environment// dlclose(handle);returntrue;// continue}// 执行HIDL_FETCH_ICameraProvider函数,参数为legacy/0
ret =(*generator)(name.c_str());if(ret ==nullptr){LOG(ERROR)<<"Could not find instance '"<< name.c_str()<<"' in library "<< lib
<<". Keeping library open.";// dlclose too problematic in multi-threaded environment// dlclose(handle);// this module doesn't provide this particular instancereturntrue;// continue}// Actual fqname might be a subclass.// This assumption is tested in vts_treble_vintf_testusing::android::hardware::details::getDescriptor;
std::string actualFqName =getDescriptor(ret.get());CHECK(actualFqName.size()>0);registerReference(actualFqName, name);returnfalse;});return ret;}HIDL_FETCH_ICameraProvider
// hardware/interfaces/camera/provider/2.4/default/CameraProvider_2_4.cpp// 参数name为legacy/0
ICameraProvider*HIDL_FETCH_ICameraProvider(constchar* name){usingnamespace android::hardware::camera::provider::V2_4::implementation;
ICameraProvider* provider =nullptr;if(strcmp(name, kLegacyProviderName)==0){// 执行这里
provider =getProviderImpl<LegacyCameraProviderImpl_2_4>();}elseif(strcmp(name, kExternalProviderName)==0){
provider =getProviderImpl<ExternalCameraProviderImpl_2_4>();}else{ALOGE("%s: unknown instance name: %s", __FUNCTION__, name);}return provider;}// 创建CameraProvider对象并返回,在CameraProvider的构造函数中,会执行IMPL的构造函数,// 也就是LegacyCameraProviderImpl_2_4的构造函数template<typenameIMPL>
CameraProvider<IMPL>*getProviderImpl(){
CameraProvider<IMPL>*provider =newCameraProvider<IMPL>();if(provider ==nullptr){ALOGE("%s: cannot allocate camera provider!", __FUNCTION__);returnnullptr;}if(provider->isInitFailed()){ALOGE("%s: camera provider init failed!", __FUNCTION__);delete provider;returnnullptr;}return provider;}LegacyCameraProviderImpl_2_4的构造函数实现
// hardware/interfaces/camera/provider/2.4/default/LegacyCameraProviderImpl_2_4.cppLegacyCameraProviderImpl_2_4::LegacyCameraProviderImpl_2_4():camera_module_callbacks_t({sCameraDeviceStatusChange,
sTorchModeStatusChange}){
mInitFailed =initialize();}上面创建了LegacyCameraProviderImpl_2_4对象,并执行了其初始化函数initialize()。
总结一句其实就是CameraProvider进程启动时加载android.hardware.camera.provider@2.4-impl.so库并执行LegacyCameraProviderImpl_2_4的初始化函数。
好的,本节就先介绍到这里,下节继续接着讲解。


发布评论