分享

Android 5.0 Camera系统源码分析:CameraService启动流程

 Elaine个人小馆 2016-09-29

1. 前言

本文将分析android系统源码,从frameworks层到hal层,暂不涉及app层和kernel层。由于某些函数比较复杂,在贴出代码时会适当对其进行简化。本文属于自己对源码的总结,仅仅是贯穿代码流程,不会深入分析各个细节。


分析android系统源码,需要对android系统的某些知识点有所了解

涉及的知识点有:

(1)Android系统的智能指针 - 参考老罗的Android系统的智能指针(轻量级指针、强指针和弱指针)的实现原理分析

(2)Android进程间通信Binder - 参考老罗的Android进程间通信(IPC)机制Binder简要介绍和学习计划

(3)Android硬件抽象层(HAL) - 参考老罗的Android硬件抽象层(HAL)概要介绍和学习计划

2. frameworks层

Android的各个子模块的启动都是从它们的Service的启动开始的,所以我们将从CameraService的启动开始分析。CameraService的启动就在MediaServer的main函数中,代码路径在:frameworks/av/media/mediaserver/main_mediaserver.cpp

int main(int argc __unused, char** argv){ ...... CameraService::instantiate(); ......}

CameraService类定义如下:

class CameraService : public BinderService, public BnCameraService, public IBinder::DeathRecipient, public camera_module_callbacks_t{ static char const* getServiceName() { return 'media.camera'; } ......}

mediaserver的main函数中调用了CameraService的instantiate函数来创建实例,该函数的实现在其父类BinderService中实现

templateclass BinderService{ static status_t publish(bool allowIsolated = false) { sp sm(defaultServiceManager()); return sm->addService( String16(SERVICE::getServiceName()), new SERVICE(), allowIsolated); } static void instantiate() { publish(); }}

1. instantiate函数只是简单的调用了publish函数

2. publish函数先构造CameraService,再通过addService函数将它注册到ServiceManager当中,而getServiceName函数获取到的值为“media camera”。这一切都是为了binder通信做准备

3. 这里使用了c++模版,从上面的CameraService类定义中可以看出,这里的SERVICE等于CameraService,也就是说publish函数中的new SERVICE等于new CameraService

4. 同时还使用了智能指针,也就是说除了调用CameraService的构造函数外,还会调用onFirstRef函数

CameraService::CameraService() :mSoundRef(0), mModule(0){ ALOGI('CameraService started (pid=%d)', getpid()); gCameraService = this; for (size_t i = 0; i < max_cameras;="" ++i)="" {="" mstatuslist[i]="ICameraServiceListener::STATUS_PRESENT;" }="" this-="">camera_device_status_change = android::camera_device_status_change;}void CameraService::onFirstRef(){ LOG1('CameraService::onFirstRef'); BnCameraService::onFirstRef(); if (hw_get_module(CAMERA_HARDWARE_MODULE_ID, (const hw_module_t **)&mModule) < 0)="" {="" aloge('could="" not="" load="" camera="" hal="" module');="" mnumberofcameras="0;" }="" else="" {="" alogi('loaded="" \'%s\'="" camera="" module',="" mmodule-="">common.name); mNumberOfCameras = mModule->get_number_of_cameras(); if (mNumberOfCameras > MAX_CAMERAS) { ALOGE('Number of cameras(%d) > MAX_CAMERAS(%d).', mNumberOfCameras, MAX_CAMERAS); mNumberOfCameras = MAX_CAMERAS; } for (int i = 0; i < mnumberofcameras;="" i++)="" {="" log1('setcamerafree(%d)',="" i);="" setcamerafree(i);="" }="" if="" (mmodule-="">common.module_api_version >= CAMERA_MODULE_API_VERSION_2_1) { mModule->set_callbacks(this); } VendorTagDescriptor::clearGlobalVendorTagDescriptor(); if (mModule->common.module_api_version >= CAMERA_MODULE_API_VERSION_2_2) { setUpVendorTags(); } CameraDeviceFactory::registerService(this); } }

第20行. 通过hw_get_module函数加载了一个hw_module_t模块,这个模块是与hal层对接的接口,ID为CAMERA_HARDWARE_MODULE_ID,并将它保存在mModule成员变量中。

第27行. 通过mModule->get_number_of_cameras函数进入到hal层,获取到了camera的个数。这个函数很重要,对于frameworks层来说只是拿到了camera的个数,但对于hal层和drivers层来说Camera的上电和初始化流程都是从这里开始的

3. hal层-基于MTK平台

先来看看mtk camera module的定义,代码路径在:vendor/mediatek/proprietary/hardware/mtkcam/module_hal/module/module.h

staticcamera_moduleget_camera_module(){ camera_module module = { common:{ tag : HARDWARE_MODULE_TAG, #if (PLATFORM_SDK_VERSION >= 21) module_api_version : CAMERA_MODULE_API_VERSION_2_3, #else module_api_version : CAMERA_DEVICE_API_VERSION_1_0, #endif hal_api_version : HARDWARE_HAL_API_VERSION, id : CAMERA_HARDWARE_MODULE_ID, name : 'MediaTek Camera Module', author : 'MediaTek', methods : get_module_methods(), dso : NULL, reserved : {0}, }, get_number_of_cameras : get_number_of_cameras, get_camera_info : get_camera_info, set_callbacks : set_callbacks, get_vendor_tag_ops : get_vendor_tag_ops, #if (PLATFORM_SDK_VERSION >= 21) open_legacy : open_legacy, #endif reserved : {0}, }; return module;};
1. 保存在frameworks层CameraService的成员变量mModule里面的就是上面这个module结构体

2. 当frameworks层调用mModule->get_number_of_cameras函数时,实际就是调用上面结构体的get_number_of_cameras函数

CamDeviceManagerImp gCamDeviceManager;ICamDeviceManager*getCamDeviceManager(){ return &gCamDeviceManager;}staticintget_number_of_cameras(void){ return NSCam::getCamDeviceManager()->getNumberOfDevices();}
1. 这里先通过getCamDeviceManager函数获取了CamDeviceManagerImp对象

2. CamDeviceManagerImp继承了CamDeviceManagerBase,这里的getNumberOfDevices方法将由父类CamDeviceManagerBase实现

int32_tCamDeviceManagerBase::getNumberOfDevices(){ mi4DeviceNum = enumDeviceLocked(); return mi4DeviceNum;}

这里只是调用了enumDeviceLocked函数,并将它的返回值(代表了camera的个数)返回到frameworks层。接着看enumDeviceLocked的实现

int32_tCamDeviceManagerImp::enumDeviceLocked(){ IHalSensorList*const pHalSensorList = IHalSensorList::get(); size_t const sensorNum = pHalSensorList->searchSensors(); for (size_t i = 0; i < sensornum;="" i++)="" {="" int32_t="" const="" deviceid="i;"> pInfo = new EnumInfo; mEnumMap.add(deviceId, pInfo); IMetadataProvider> pMetadataProvider = IMetadataProvider::create(deviceId); pInfo->pMetadata = pMetadataProvider->getStaticCharacteristics(); pInfo->iFacing = (pMetadataProvider->getDeviceFacing() == MTK_LENS_FACING_FRONT) ? CAMERA_FACING_FRONT : CAMERA_FACING_BACK ; pInfo->iWantedOrientation = pMetadataProvider->getDeviceWantedOrientation(); pInfo->iSetupOrientation = pMetadataProvider->getDeviceSetupOrientation(); i4DeviceNum++; } return i4DeviceNum;}

第5-6行. 这里需要重点关注pHalSensorList->searchSensors函数,它的返回值就是camera的个数

第8-24行. 循环构造并初始化一个EnumInfo对象,并把它保存在mEnumMap中

MUINTHalSensorList::enumerateSensor_Locked(){ int ret_count = 0; SensorDrv *const pSensorDrv = SensorDrv::get(); int const iSensorsList = pSensorDrv->impSearchSensor(NULL); if((iSensorsList & SENSOR_DEV_MAIN) == SENSOR_DEV_MAIN) { halSensorDev = SENSOR_DEV_MAIN; pSensorInfo = pSensorDrv->getMainSensorInfo(); addAndInitSensorEnumInfo_Locked(halSensorDev, ret_count, mapToSensorType(pSensorInfo->GetType()), pSensorInfo->getDrvMacroName()); ret_count++; } if((iSensorsList & SENSOR_DEV_SUB) == SENSOR_DEV_SUB) { halSensorDev = SENSOR_DEV_SUB; pSensorInfo = pSensorDrv->getSubSensorInfo(); addAndInitSensorEnumInfo_Locked(halSensorDev, ret_count, mapToSensorType(pSensorInfo->GetType()), pSensorInfo->getDrvMacroName()); ret_count++; } mEnumSensorCount = ret_count; return ret_count;}MUINTHalSensorList::searchSensors(){ return enumerateSensor_Locked();}

第33行. searchSensors函数只是调用了enumerateSensor_Locked函数,这里并没有贴出enumerateSensor_Locked函数的所有代码,删减了一些我们暂时不关注的东西

第7行. 重点函数pSensorDrv->impSearchSensor,它的返回值决定了enumerateSensor_Locked的返回值,也就是camera的个数

MINT32ImgSensorDrv::impSearchSensor(pfExIdChk pExIdChkCbf){ MUINT32 SensorEnum = (MUINT32) DUAL_CAMERA_MAIN_SENSOR; MUINT32 i,id[KDIMGSENSOR_MAX_INVOKE_DRIVERS] = {0,0}; MINT32 sensorDevs = SENSOR_NONE; GetSensorInitFuncList(&m_pstSensorInitFunc); m_fdSensor = ::open('/dev/kd_camera_hw', O_RDWR); for (SensorEnum = DUAL_CAMERA_MAIN_SENSOR; SensorEnum <= dual_camera_sub_sensor;="" sensorenum=""><= 1)="" {="" for="" (i="0;" i="">< max_num_of_support_sensor;="" i++)="" {="" end="" of="" driver="" list="" if="" (m_pstsensorinitfunc[i].getcameradefault="=" null)="" {="" log_msg('m_pstsensorinitfunc[i].getcameradefault="" is="" null:="" %d="" \n',="" i);="" break;="" }="" id[kdimgsensor_invoke_driver_0]="(SensorEnum">< kdimgsensor_dual_shift)="" |="" i;="" err="ioctl(m_fdSensor," kdimgsensorioc_x_set_driver,&id[kdimgsensor_invoke_driver_0]="" );="" err="ioctl(m_fdSensor," kdimgsensorioc_t_check_is_alive);="" if="" (err="">< 0="" ||="" err2="">< 0)="" {="" log_msg('sensor="" id="" mismatch\n');="" continue;="" }="" if="" (sensorenum="=" dual_camera_main_sensor)="" {="" m_mainsensordrv.index[m_mainsensordrv.number]="i;" m_mainsensordrv.type[m_mainsensordrv.number]="sensorType;" m_mainsensordrv.position="socketPos;" m_mainsensordrv.sensorid="m_pstSensorInitFunc[m_mainSensorDrv.index[m_mainSensorDrv.number]].SensorId;" m_mainsensordrv.number++;="" }="" else="" if="" (sensorenum="=" dual_camera_sub_sensor)="" {="" m_subsensordrv.index[m_subsensordrv.number]="i;" m_subsensordrv.type[m_subsensordrv.number]="sensorType;" m_subsensordrv.position="socketPos;" m_subsensordrv.sensorid="m_pstSensorInitFunc[m_subSensorDrv.index[m_subSensorDrv.number]].SensorId;" m_subsensordrv.number++;="" }="" }="" }="" if="" (bad_sensor_index="" !="m_mainSensorDrv.index[0])" {="" m_mainsensorid="m_mainSensorDrv.sensorID;" m_mainsensoridx="m_mainSensorDrv.index[0];" sensordevs="" |="SENSOR_MAIN;" }="" if="" (bad_sensor_index="" !="m_subSensorDrv.index[0])" {="" m_subsensorid="m_subSensorDrv.sensorID;" m_subsensoridx="m_subSensorDrv.index[0];" sensordevs="" |="SENSOR_SUB;" }="" return="">

这个函数比较长,所以只贴出关键代码

第8行, 调用GetSensorInitFuncList函数来获取hal层的sersors列表,并把它保存在m_pstSensorInitFunc变量中

第9行, 通过系统调用open函数打开camera的设备节点,后面会通过这个节点来进入到kernel层

第11-12行, 通过两个for循环来遍历sensorlist中所有可能存在的camera

第20行, 通过ioctl下达setDriver指令,并下传正在遍历的sensorlist中的ID。Driver层根据这个ID,挂载Driver层sensorlist中对应的操作接口

第21行, 通过ioctl下达check ID指令,Driver层为对应sensor上电,通过I2C读取预存在寄存器中的sensor id。然后比较读取结果,如果不匹配return error后继续遍历

第29-41行, 将sensor相关的信息保存在m_mainSensorDrv和m_subSensorDrv中

第45-56行, 给sensroDevs变量赋值,并将它返回给上一级

这里暂不分析kernel层的代码,先来看看GetSensorInitFuncList函数,代码在sensorlist.cpp中

MSDK_SENSOR_INIT_FUNCTION_STRUCT SensorList[] ={#if defined(IMX175_MIPI_RAW) RAW_INFO(IMX175_SENSOR_ID, SENSOR_DRVNAME_IMX175_MIPI_RAW,NULL),#endif#if defined(IMX179_MIPI_RAW) RAW_INFO(IMX179_SENSOR_ID, SENSOR_DRVNAME_IMX179_MIPI_RAW,NULL),#endif#if defined(IMX219_MIPI_RAW) RAW_INFO(IMX219_SENSOR_ID, SENSOR_DRVNAME_IMX219_MIPI_RAW, NULL),#endif#if defined(IMX214_MIPI_RAW) RAW_INFO(IMX214_SENSOR_ID, SENSOR_DRVNAME_IMX214_MIPI_RAW,NULL),#endif#if defined(GC2235_RAW) RAW_INFO(GC2235_SENSOR_ID, SENSOR_DRVNAME_GC2235_RAW, NULL),#endif#if defined(GC2035_YUV) YUV_INFO(GC2035_SENSOR_ID, SENSOR_DRVNAME_GC2035_YUV, NULL),#endif ......}UINT32 GetSensorInitFuncList(MSDK_SENSOR_INIT_FUNCTION_STRUCT **ppSensorList){ *ppSensorList = &SensorList[0]; return MHAL_NO_ERROR;}
hal层的sensorList,再熟悉不过的代码,需要注意的是hal层sensorList和kernel层的sensorList顺序必须保持一致

4. 总结

至此,除kernel层外,简述了CameraService的启动流程,大概过程如下图所示



    本站是提供个人知识管理的网络存储空间,所有内容均由用户发布,不代表本站观点。请注意甄别内容中的联系方式、诱导购买等信息,谨防诈骗。如发现有害或侵权内容,请点击一键举报。
    转藏 分享 献花(0

    0条评论

    发表

    请遵守用户 评论公约

    类似文章 更多