Camera系统架构
Camera的架构与Android系统的整体架构保持一致,如下图所示,本文主要从以下四个方面对其进行说明。
Framework:Camera.java
Android Runtime:android_hardware_Camera.cpp
Library:Camera Client和Camera Service
HAL:CameraHardwareInterface
一、Framework:Camera.java
Camera是应用层软件直接使用的类,涵盖了启动、预览、拍摄及关闭等操作摄像头的全部接口。Camera.java在Android源码中的路径为:framework/base/core/java/android/hardware。为了说明整个Camera系统的架构,这里暂不横向分析Camera.java的功能,下面从open()方法着手:
publicstaticCameraopen(){intnumberOfCameras=getNumberOfCameras();CameraInfocameraInfo=newCameraInfo();for(inti=0;i<numberOfCameras;i++){getCameraInfo(i,cameraInfo);if(cameraInfo.facing==CameraInfo.CAMERA_FACING_BACK){returnnewCamera(i);}}returnnull;}
open()方法需要注意以下几点:
getNumberOfCameras为native方法,实现在android_hardware_Camera.cpp中;
CameraInfo是Camera定义的静态内部类,包含facing、orientation、canDisableShutterSound;
getCameraInfo内部调用native方法_getCameraInfo获取摄像头信息;
open()默认启动的是后置摄像头(CAMERA_FACING_BACK)。
/**usedbyCamera#open,Camera#open(int)*/Camera(intcameraId){interr=cameraInitNormal(cameraId);if(checkInitErrors(err)){switch(err){caseEACCESS:thrownewRuntimeException("Failtoconnecttocameraservice");caseENODEV:thrownewRuntimeException("Camerainitializationfailed");default://Shouldneverhitthis.thrownewRuntimeException("Unknowncameraerror");}}}
Camera构造器的核心实现在cameraInitNormal中,cameraInitNormal调用cameraInitVersion,并传入参数cameraId和CAMERA_HAL_API_VERSION_NORMAL_CONNECT,后者代表HAL的版本。
privateintcameraInitVersion(intcameraId,inthalVersion){
……
StringpackageName=ActivityThread.currentPackageName();returnnative_setup(newWeakReference<Camera>(this),cameraId,halVersion,packageName);}
cameraInitNormal调用本地方法native_setup(),由此进入到android_hardware_Camera.cpp中,native_setup()的签名如下:
privatenativefinalintnative_setup(Objectcamera_this,intcameraId,inthalVersion,StringpackageName);二、Android Runtime:android_hardware_Camera.cpp
native_setup()被动态注册到JNI,通过JNI调用android_hardware_Camera_native_setup()方法。
staticJNINativeMethodcamMethods[]={……{"native_setup","(Ljava/lang/Object;ILjava/lang/String;)V",(void*)android_hardware_Camera_native_setup}……};
JNI的重点是android_hardware_Camera_native_setup()方法的实现:
//connecttocameraservicestaticjintandroid_hardware_Camera_native_setup(JNIEnv*env,jobjectthiz,jobjectweak_this,jintcameraId,jinthalVersion,jstringclientPackageName){//ConvertjstringtoString16constchar16_t*rawClientName=env->GetStringChars(clientPackageName,NULL);jsizerawClientNameLen=env->GetStringLength(clientPackageName);String16clientName(rawClientName,rawClientNameLen);env->ReleaseStringChars(clientPackageName,rawClientName);sp<Camera>camera;if(halVersion==CAMERA_HAL_API_VERSION_NORMAL_CONNECT){//Defaultpath:halversionisdon'tcare,donormalcameraconnect.camera=Camera::connect(cameraId,clientName,Camera::USE_CALLING_UID);}else{jintstatus=Camera::connectLegacy(cameraId,halVersion,clientName,Camera::USE_CALLING_UID,camera);if(status!=NO_ERROR){returnstatus;}}if(camera==NULL){return-EACCES;}//makesurecamerahardwareisaliveif(camera->getStatus()!=NO_ERROR){returnNO_INIT;}jclassclazz=env->GetObjectClass(thiz);if(clazz==NULL){//ThisshouldneverhappenjniThrowRuntimeException(env,"Can'tfindandroid/hardware/Camera");returnINVALID_OPERATION;}//WeuseaweakreferencesotheCameraobjectcanbegarbagecollected.//Thereferenceisonlyusedasaproxyforcallbacks.sp<JNICameraContext>context=newJNICameraContext(env,weak_this,clazz,camera);context->incStrong((void*)android_hardware_Camera_native_setup);camera->setListener(context);//savecontextinopaquefieldenv->SetLongField(thiz,fields.context,(jlong)context.get());returnNO_ERROR;}
android_hardware_Camera_native_setup()方法通过调用Camera::connect()方法请求连接CameraService服务。入参中:
clientName是通过将clientPackageName从jstring转换为String16格式得到;
Camera::USE_CALLING_UID是定义在Camera.h中的枚举类型,其值为ICameraService::USE_CALLING_UID(同样为枚举类型,值为-1)。
Camera::connect()位于Camera.cpp中,由此进入到Library层。
三、Library:Camera Client和Camera Service如上述架构图中所示,ICameraService.h、ICameraClient.h和ICamera.h三个类定义了Camera的接口和架构,ICameraService.cpp和Camera.cpp两个文件用于Camera架构的实现,Camera的具体功能在下层调用硬件相关的接口来实现。Camera.h是Camera系统对上层的接口。
具体的,Camera类继承模板类CameraBase,Camera::connect()调用了CameraBase.cpp中的connect()方法。
sp<Camera>Camera::connect(intcameraId,constString16&clientPackageName,intclientUid){returnCameraBaseT::connect(cameraId,clientPackageName,clientUid);}
CameraBase实际上又继承了IBinder的DeathRecipient内部类,DeathRecipient虚拟继承自RefBase。RefBase是Android中的引用计数基础类,其中定义了incStrong、decStrong、incWeak和decWeak等涉及sp/wp的指针操作函数,当然这扯远了。
template<typenameTCam>structCameraTraits{};template<typenameTCam,typenameTCamTraits=CameraTraits<TCam>>classCameraBase:publicIBinder::DeathRecipient{public:staticsp<TCam>connect(intcameraId,constString16&clientPackageName,intclientUid);……}
classDeathRecipient:publicvirtualRefBase{public:virtualvoidbinderDied(constwp<IBinder>&who)=0;};
回到Camera::connect()的实现上,其中,newTCam(cameraId)生成BnCameraClient对象,BnCameraClient定义在ICameraClient.h文件中,继承自模板类BnInterface。getCameraService()方法返回CameraService的服务代理BpCameraService,BpCameraService同样继承自模板类BnInterface。然后通过Binder通信发送CONNECT命令,当BnCameraService收到CONNECT命令后调用CameraService的connect()成员函数来做相应的处理。
template<typenameTCam,typenameTCamTraits>sp<TCam>CameraBase<TCam,TCamTraits>::connect(intcameraId,constString16&clientPackageName,intclientUid){ALOGV("%s:connect",__FUNCTION__);sp<TCam>c=newTCam(cameraId);//BnCameraClientsp<TCamCallbacks>cl=c;status_tstatus=NO_ERROR;constsp<ICameraService>&cs=getCameraService();//BpCameraServiceif(cs!=0){TCamConnectServicefnConnectService=TCamTraits::fnConnectService;status=(cs.get()->*fnConnectService)(cl,cameraId,clientPackageName,clientUid,/*out*/c->mCamera);}if(status==OK&&c->mCamera!=0){c->mCamera->asBinder()->linkToDeath(c);c->mStatus=NO_ERROR;}else{ALOGW("Anerroroccurredwhileconnectingtocamera:%d",cameraId);c.clear();}returnc;}
classBnCameraClient:publicBnInterface<ICameraClient>{public:virtualstatus_tonTransact(uint32_tcode,constParcel&data,Parcel*reply,uint32_tflags=0);};
classBpCameraService:publicBpInterface<ICameraService>{public:BpCameraService(constsp<IBinder>&impl):BpInterface<ICameraService>(impl){}……}
注:connect()函数在BpCameraService和BnCameraService的父类ICameraService中声明为纯虚函数,在BpCameraService和CameraService中分别给出了实现,BpCameraService作为代理类,提供接口给客户端,真正实现在BnCameraService的子类CameraService中。
在BpCameraService中,connect()函数实现如下:
//connecttocameraservice(android.hardware.Camera)virtualstatus_tconnect(constsp<ICameraClient>&cameraClient,intcameraId,constString16&clientPackageName,intclientUid,/*out*/sp<ICamera>&device){Parceldata,reply;data.writeInterfaceToken(ICameraService::getInterfaceDescriptor());data.writeStrongBinder(cameraClient->asBinder());data.writeInt32(cameraId);data.writeString16(clientPackageName);data.writeInt32(clientUid);remote()->transact(BnCameraService::CONNECT,data,&reply);//BpBinder的transact()函数向IPCThreadState实例发送消息,通知其有消息要发送给binderdriver
if(readExceptionCode(reply))return-EPROTO;status_tstatus=reply.readInt32();if(reply.readInt32()!=0){device=interface_cast<ICamera>(reply.readStrongBinder());//client端读出server返回的bind}returnstatus;}
首先将传递过来的Camera对象cameraClient转换成IBinder类型,将调用的参数写到Parcel(可理解为Binder通信的管道)中,通过BpBinder的transact()函数发送消息,然后由BnCameraService去响应该连接,最后就是等待服务端返回,如果成功则生成一个BpCamera实例。
真正的服务端响应实现在BnCameraService的onTransact()函数中,其负责解包收到的Parcel并执行client端的请求的方法。
status_tBnCameraService::onTransact(uint32_tcode,constParcel&data,Parcel*reply,uint32_tflags){switch(code){
……caseCONNECT:{CHECK_INTERFACE(ICameraService,data,reply);sp<ICameraClient>cameraClient=interface_cast<ICameraClient>(data.readStrongBinder());//使用Camera的Binder对象生成Camera客户代理BpCameraClient实例int32_tcameraId=data.readInt32();constString16clientName=data.readString16();int32_tclientUid=data.readInt32();sp<ICamera>camera;status_tstatus=connect(cameraClient,cameraId,clientName,clientUid,/*out*/camera);//将生成的BpCameraClient对象作为参数传递到CameraService的connect()函数中reply->writeNoException();reply->writeInt32(status);//将BpCamera对象以IBinder的形式打包到Parcel中返回if(camera!=NULL){reply->writeInt32(1);reply->writeStrongBinder(camera->asBinder());}else{reply->writeInt32(0);}returnNO_ERROR;}break;……}}
主要的处理包括:
通过data中Camera的Binder对象生成Camera客户代理BpCameraClient实例;
将生成的BpCameraClient对象作为参数传递到CameraService(/frameworks/av/services/camera /libcameraservice/CameraService.cpp)的connect()函数中,该函数会返回一个BpCamera实例;
将在上述实例对象以IBinder的形式打包到Parcel中返回。
最后,BpCamera实例是通过CameraService::connect()函数返回的。CameraService::connect()实现的核心是调用connectHelperLocked()函数根据HAL不同API的版本创建不同的client实例(早期版本中好像没有connectHelperLocked()这个函数,但功能基本相似)。
status_tCameraService::connectHelperLocked(/*out*/sp<Client>&client,/*in*/constsp<ICameraClient>&cameraClient,intcameraId,constString16&clientPackageName,intclientUid,intcallingPid,inthalVersion,boollegacyMode){intfacing=-1;intdeviceVersion=getDeviceVersion(cameraId,&facing);if(halVersion<0||halVersion==deviceVersion){//Defaultpath:HALversionisunspecifiedbycaller,createCameraClient//basedondeviceversionreportedbytheHAL.switch(deviceVersion){caseCAMERA_DEVICE_API_VERSION_1_0:client=newCameraClient(this,cameraClient,clientPackageName,cameraId,facing,callingPid,clientUid,getpid(),legacyMode);break;caseCAMERA_DEVICE_API_VERSION_2_0:caseCAMERA_DEVICE_API_VERSION_2_1:caseCAMERA_DEVICE_API_VERSION_3_0:caseCAMERA_DEVICE_API_VERSION_3_1:caseCAMERA_DEVICE_API_VERSION_3_2:client=newCamera2Client(this,cameraClient,clientPackageName,cameraId,facing,callingPid,clientUid,getpid(),legacyMode);break;case-1:ALOGE("Invalidcameraid%d",cameraId);returnBAD_VALUE;default:ALOGE("UnknowncameradeviceHALversion:%d",deviceVersion);returnINVALID_OPERATION;}}else{//AparticularHALversionisrequestedbycaller.CreateCameraClient//basedontherequestedHALversion.if(deviceVersion>CAMERA_DEVICE_API_VERSION_1_0&&halVersion==CAMERA_DEVICE_API_VERSION_1_0){//OnlysupporthigherHALversiondeviceopenedasHAL1.0device.client=newCameraClient(this,cameraClient,clientPackageName,cameraId,facing,callingPid,clientUid,getpid(),legacyMode);}else{//Othercombinations(e.g.HAL3.xopenasHAL2.x)arenotsupportedyet.ALOGE("InvalidcameraHALversion%x:HAL%xdevicecanonlybe""openedasHAL%xdevice",halVersion,deviceVersion,CAMERA_DEVICE_API_VERSION_1_0);returnINVALID_OPERATION;}}status_tstatus=connectFinishUnsafe(client,client->getRemote());if(status!=OK){//thisisprobablynotrecoverable..maybetheclientcantryagainreturnstatus;}mClient[cameraId]=client;LOG1("CameraService::connectX(id%d,thispidis%d)",cameraId,getpid());returnOK;}
可见,在CAMERA_DEVICE_API_VERSION_2_0之前使用CameraClient进行实例化,之后则采用Camera2Client进行实例化。以CameraClient为例,其initialize()函数如下:
status_tCameraClient::initialize(camera_module_t*module){intcallingPid=getCallingPid();status_tres;LOG1("CameraClient::initializeE(pid%d,id%d)",callingPid,mCameraId);//Verifyopspermissionsres=startCameraOps();if(res!=OK){returnres;}charcamera_device_name[10];snprintf(camera_device_name,sizeof(camera_device_name),"%d",mCameraId);mHardware=newCameraHardwareInterface(camera_device_name);res=mHardware->initialize(&module->common);if(res!=OK){ALOGE("%s:Camera%d:unabletoinitializedevice:%s(%d)",__FUNCTION__,mCameraId,strerror(-res),res);mHardware.clear();returnres;}mHardware->setCallbacks(notifyCallback,dataCallback,dataCallbackTimestamp,(void*)(uintptr_t)mCameraId);//Enablezoom,error,focus,andmetadatamessagesbydefaultenableMsgType(CAMERA_MSG_ERROR|CAMERA_MSG_ZOOM|CAMERA_MSG_FOCUS|CAMERA_MSG_PREVIEW_METADATA|CAMERA_MSG_FOCUS_MOVE);LOG1("CameraClient::initializeX(pid%d,id%d)",callingPid,mCameraId);returnOK;}
上述函数中,主要注意以下流程:
加粗的代码CameraHardwareInterface新建了了一个Camera硬件接口,当然,camera_device_name为摄像头设备名;
mHardware->initialize(&module->common)调用底层硬件的初始化方法;
mHardware->setCallbacks将CamerService处的回调函数注册到HAL处。
CameraHardwareInterface定义了Camera的硬件抽象特征,由此进入到HAL。
四、HAL:CameraHardwareInterfaceCameraHardwareInterface的作用在于链接Camera Server和V4L2,通过实现CameraHardwareInterface可以屏蔽不同的driver对Camera Server的影响。CameraHardwareInterface同样虚拟继承自RefBase。
classCameraHardwareInterface:publicvirtualRefBase{public:CameraHardwareInterface(constchar*name){mDevice=0;mName=name;}……}
CameraHardwareInterface中包含了控制通道和数据通道,控制通道用于处理预览和视频获取的开始/停止、拍摄照片、自动对焦等功能,数据通道通过回调函数来获得预览、视频录制、自动对焦等数据。当需要支持新的硬件时就需要继承于CameraHardwareInterface ,来实现对应的功能。CameraHardwareInterface提供的public方法如下:
在前一节中,initialize()函数调用了mHardware->initialize和mHardware->setCallbacks,下面来看下CameraHardwareInterface.h对其的实现。
status_tinitialize(hw_module_t*module){ALOGI("Openingcamera%s",mName.string());camera_module_t*cameraModule=reinterpret_cast<camera_module_t*>(module);camera_infoinfo;status_tres=cameraModule->get_camera_info(atoi(mName.string()),&info);if(res!=OK)returnres;intrc=OK;if(module->module_api_version>=CAMERA_MODULE_API_VERSION_2_3&&info.device_version>CAMERA_DEVICE_API_VERSION_1_0){//OpenhigherversioncameradeviceasHAL1.0device.rc=cameraModule->open_legacy(module,mName.string(),CAMERA_DEVICE_API_VERSION_1_0,(hw_device_t**)&mDevice);}else{rc=CameraService::filterOpenErrorCode(module->methods->open(module,mName.string(),(hw_device_t**)&mDevice));}if(rc!=OK){ALOGE("Couldnotopencamera%s:%d",mName.string(),rc);returnrc;}initHalPreviewWindow();returnrc;}
在initialize()方法中,通过cameraModule->open_legacy打开摄像头模组,initHalPreviewWindow()用于初始化Preview的相关流opspreview_stream_ops,初始化hal的预览窗口。
voidinitHalPreviewWindow(){mHalPreviewWindow.nw.cancel_buffer=__cancel_buffer;mHalPreviewWindow.nw.lock_buffer=__lock_buffer;mHalPreviewWindow.nw.dequeue_buffer=__dequeue_buffer;mHalPreviewWindow.nw.enqueue_buffer=__enqueue_buffer;mHalPreviewWindow.nw.set_buffer_count=__set_buffer_count;mHalPreviewWindow.nw.set_buffers_geometry=__set_buffers_geometry;mHalPreviewWindow.nw.set_crop=__set_crop;mHalPreviewWindow.nw.set_timestamp=__set_timestamp;mHalPreviewWindow.nw.set_usage=__set_usage;mHalPreviewWindow.nw.set_swap_interval=__set_swap_interval;mHalPreviewWindow.nw.get_min_undequeued_buffer_count=__get_min_undequeued_buffer_count;}
/**Setthenotificationanddatacallbacks*/voidsetCallbacks(notify_callbacknotify_cb,data_callbackdata_cb,data_callback_timestampdata_cb_timestamp,void*user){mNotifyCb=notify_cb;mDataCb=data_cb;mDataCbTimestamp=data_cb_timestamp;mCbUser=user;ALOGV("%s(%s)",__FUNCTION__,mName.string());if(mDevice->ops->set_callbacks){mDevice->ops->set_callbacks(mDevice,__notify_cb,__data_cb,__data_cb_timestamp,__get_memory,this);}}
set_callbacks中,__notify_cb、__data_cb、__data_cb_timestamp和__get_memory分别消息回调,数据回调,时间戳回调,以及内存相关操作的回调。
以上通过简略分析应用层调用Camera.open()之后在Framework、ART、Library以及HAL层的响应,来说明Android中Camera系统的整体架构
声明:本站所有文章资源内容,如无特殊说明或标注,均为采集网络资源。如若本站内容侵犯了原著者的合法权益,可联系本站删除。