Android(安卓)Camera 系统框架分析
用心的文章要转
一、在android中开发人员可以做那些工作?
应用程序开发:利用android提供的强大的sdk,开发出各种各样新颖的应用。
系统开发:在android中Google实现了与硬件无关的所有代码,但是与硬件密切相关的硬件抽象层却没有也无法提供,对于移动设备不同的设备提供商底层硬件是千变万化的,不可能提供统一的硬件驱动以及接口实现,只能提供标准的接口,因此硬件提供商需要自个儿开发设备驱动,
并去实现android框架提供的接口。
二、android框架中Camera系统源码分析
在每个android手机中都有一个Camera应用程序用来实现拍照功能,不同硬件提供商可能会对这个应用程序进行改变来适合自己的UI风格,
这里仅仅分析android原生Camera应用以及框架(Android 4.0)
原生Camera应用代码在Camera.java(android4.0\packages\apps\camera\src\com\android\camera),这个应该算是Camera系统最上层,应用层的实现。
下面是Camera类部分代码
- publicclassCameraextendsActivityBaseimplementsFocusManager.Listener,
- View.OnTouchListener,ShutterButton.OnShutterButtonListener,
- SurfaceHolder.Callback,ModePicker.OnModeChangeListener,
- FaceDetectionListener,CameraPreference.OnPreferenceChangedListener,
- LocationManager.Listener,ShutterButton.OnShutterButtonLongPressListener
可以重载OnCreate、OnResume等接口,在这些接口中完成相关初始化的工作,基本就是初始化各种监听对象,以及获取相机参数等相关。
比较关键的在doOnResume这个函数中:
[java] view plain copy
- @Override
- protectedvoiddoOnResume(){
- if(mOpenCameraFail||mCameraDisabled)return;
- mPausing=false;
- mJpegPictureCallbackTime=0;
- mZoomValue=0;
- //Startthepreviewifitisnotstarted.
- if(mCameraState==PREVIEW_STOPPED){
- try{
- mCameraDevice=Util.openCamera(this,mCameraId);
- initializeCapabilities();
- resetExposureCompensation();
- startPreview();
- if(mFirstTimeInitialized)startFaceDetection();
- }catch(CameraHardwareExceptione){
- Util.showErrorAndFinish(this,R.string.cannot_connect_camera);
- return;
- }catch(CameraDisabledExceptione){
- Util.showErrorAndFinish(this,R.string.camera_disabled);
- return;
- }
- }
- if(mSurfaceHolder!=null){
- //Iffirsttimeinitializationisnotfinished,putitinthe
- //messagequeue.
- if(!mFirstTimeInitialized){
- mHandler.sendEmptyMessage(FIRST_TIME_INIT);
- }else{
- initializeSecondTime();
- }
- }
- keepScreenOnAwhile();
- if(mCameraState==IDLE){
- mOnResumeTime=SystemClock.uptimeMillis();
- mHandler.sendEmptyMessageDelayed(CHECK_DISPLAY_ROTATION,100);
- }
- }
mCameraDevice = Util.openCamera(this, mCameraId),这里使用Util这个类,这个类的实现在
Util.java (android4.0\packages\apps\camera\src\com\android\camera)中,找到OpenCamera这个函数实现:
[java] view plain copy
- publicstaticandroid.hardware.CameraopenCamera(Activityactivity,intcameraId)
- throwsCameraHardwareException,CameraDisabledException{
- //Checkifdevicepolicyhasdisabledthecamera.
- DevicePolicyManagerdpm=(DevicePolicyManager)activity.getSystemService(
- Context.DEVICE_POLICY_SERVICE);
- if(dpm.getCameraDisabled(null)){
- thrownewCameraDisabledException();
- }
- try{
- returnCameraHolder.instance().open(cameraId);
- }catch(CameraHardwareExceptione){
- //Inengbuild,wethrowtheexceptionsothattesttool
- //candetectitandreportit
- if("eng".equals(Build.TYPE)){
- thrownewRuntimeException("openCamerafailed",e);
- }else{
- throwe;
- }
- }
- }
定位到这个类的实现CameraHolder.java (android4.0\packages\apps\camera\src\com\android\camera)通过调用open函数获取一个Camera硬件设备对象,
因为Camera设备是独享设备,不能同时被两个进程占用,而整个android系统是一个多进程环境,因此需要加入一些进程间互斥同步的方法。
定位到这个类的open函数:
[java] view plain copy
- publicsynchronizedandroid.hardware.Cameraopen(intcameraId)
- throwsCameraHardwareException{
- Assert(mUsers==0);
- if(mCameraDevice!=null&&mCameraId!=cameraId){
- mCameraDevice.release();
- mCameraDevice=null;
- mCameraId=-1;
- }
- if(mCameraDevice==null){
- try{
- Log.v(TAG,"opencamera"+cameraId);
- mCameraDevice=android.hardware.Camera.open(cameraId);
- mCameraId=cameraId;
- }catch(RuntimeExceptione){
- Log.e(TAG,"failtoconnectCamera",e);
- thrownewCameraHardwareException(e);
- }
- mParameters=mCameraDevice.getParameters();
- }else{
- try{
- mCameraDevice.reconnect();
- }catch(IOExceptione){
- Log.e(TAG,"reconnectfailed.");
- thrownewCameraHardwareException(e);
- }
- mCameraDevice.setParameters(mParameters);
- }
- ++mUsers;
- mHandler.removeMessages(RELEASE_CAMERA);
- mKeepBeforeTime=0;
- returnmCameraDevice;
- }
- publicclassCamera{
- privatestaticfinalStringTAG="Camera";
- //Thesematchtheenumsinframeworks/base/include/camera/Camera.h
- privatestaticfinalintCAMERA_MSG_ERROR=0x001;
- privatestaticfinalintCAMERA_MSG_SHUTTER=0x002;
- privatestaticfinalintCAMERA_MSG_FOCUS=0x004;
- privatestaticfinalintCAMERA_MSG_ZOOM=0x008;
- privatestaticfinalintCAMERA_MSG_PREVIEW_FRAME=0x010;
- privatestaticfinalintCAMERA_MSG_VIDEO_FRAME=0x020;
- privatestaticfinalintCAMERA_MSG_POSTVIEW_FRAME=0x040;
- privatestaticfinalintCAMERA_MSG_RAW_IMAGE=0x080;
- privatestaticfinalintCAMERA_MSG_COMPRESSED_IMAGE=0x100;
- privatestaticfinalintCAMERA_MSG_RAW_IMAGE_NOTIFY=0x200;
- privatestaticfinalintCAMERA_MSG_PREVIEW_METADATA=0x400;
- privatestaticfinalintCAMERA_MSG_ALL_MSGS=0x4FF;
- privateintmNativeContext;//accessedbynativemethods
- privateEventHandlermEventHandler;
- privateShutterCallbackmShutterCallback;
- privatePictureCallbackmRawImageCallback;
- privatePictureCallbackmJpegCallback;
- privatePreviewCallbackmPreviewCallback;
- privatePictureCallbackmPostviewCallback;
- privateAutoFocusCallbackmAutoFocusCallback;
- privateOnZoomChangeListenermZoomListener;
- privateFaceDetectionListenermFaceListener;
- privateErrorCallbackmErrorCallback;
public static Camera open(int cameraId) {
return new Camera(cameraId);
}
Open函数是一个静态方法,构造一个Camera对象:
[java] view plain copy
- Camera(intcameraId){
- mShutterCallback=null;
- mRawImageCallback=null;
- mJpegCallback=null;
- mPreviewCallback=null;
- mPostviewCallback=null;
- mZoomListener=null;
- Looperlooper;
- if((looper=Looper.myLooper())!=null){
- mEventHandler=newEventHandler(this,looper);
- }elseif((looper=Looper.getMainLooper())!=null){
- mEventHandler=newEventHandler(this,looper);
- }else{
- mEventHandler=null;
- }
- native_setup(newWeakReference<Camera>(this),cameraId);
- }
在构造函数中调用native_setup方法,此方法对应于C++代码的android_hardware_Camera_native_setup方法,
实现在android_hardware_Camera.cpp (android4.0\frameworks\base\core\jni),具体代码如下:
[cpp] view plain copy
- staticvoidandroid_hardware_Camera_native_setup(JNIEnv*env,jobjectthiz,
- jobjectweak_this,jintcameraId)
- {
- sp<Camera>camera=Camera::connect(cameraId);
- if(camera==NULL){
- jniThrowRuntimeException(env,"Failtoconnecttocameraservice");
- return;
- }
- //makesurecamerahardwareisalive
- if(camera->getStatus()!=NO_ERROR){
- jniThrowRuntimeException(env,"Camerainitializationfailed");
- return;
- }
- jclassclazz=env->GetObjectClass(thiz);
- if(clazz==NULL){
- jniThrowRuntimeException(env,"Can'tfindandroid/hardware/Camera");
- return;
- }
- //WeuseaweakreferencesotheCameraobjectcanbegarbagecollected.
- //Thereferenceisonlyusedasaproxyforcallbacks.
- sp<JNICameraContext>context=newJNICameraContext(env,weak_this,clazz,camera);
- context->incStrong(thiz);
- camera->setListener(context);
- //savecontextinopaquefield
- env->SetIntField(thiz,fields.context,(int)context.get());
- }
定位到connect方法: [cpp] view plain copy
- sp<Camera>Camera::connect(intcameraId)
- {
- LOGV("connect");
- sp<Camera>c=newCamera();
- constsp<ICameraService>&cs=getCameraService();
- if(cs!=0){
- c->mCamera=cs->connect(c,cameraId);
- }
- if(c->mCamera!=0){
- c->mCamera->asBinder()->linkToDeath(c);
- c->mStatus=NO_ERROR;
- }else{
- c.clear();
- }
- returnc;
- }
Service端实际实现相机相关的操作,Client端通过Binder接口调用Service对应的操作。
继续分析代码,上面函数调用getCameraService方法,获得CameraService的引用,ICameraService有两个子类,BnCameraService和BpCameraService,这两个子类同时也
继承了IBinder接口,这两个子类分别实现了Binder通信的两端,Bnxxx实现ICameraService的具体功能,Bpxxx利用Binder的通信功能封装ICameraService方法,具体如下:
[cpp] view plain copy
- classICameraService:publicIInterface
- {
- public:
- enum{
- GET_NUMBER_OF_CAMERAS=IBinder::FIRST_CALL_TRANSACTION,
- GET_CAMERA_INFO,
- CONNECT
- };
- public:
- DECLARE_META_INTERFACE(CameraService);
- virtualint32_tgetNumberOfCameras()=0;
- virtualstatus_tgetCameraInfo(intcameraId,
- structCameraInfo*cameraInfo)=0;
- virtualsp<ICamera>connect(constsp<ICameraClient>&cameraClient,
- intcameraId)=0;
- };
- //----------------------------------------------------------------------------
- classBnCameraService:publicBnInterface<ICameraService>
- {
- public:
- virtualstatus_tonTransact(uint32_tcode,
- constParcel&data,
- Parcel*reply,
- uint32_tflags=0);
- };
- };//na
- classBpCameraService:publicBpInterface<ICameraService>
- {
- public:
- BpCameraService(constsp<IBinder>&impl)
- :BpInterface<ICameraService>(impl)
- {
- }
- //getnumberofcamerasavailable
- virtualint32_tgetNumberOfCameras()
- {
- Parceldata,reply;
- data.writeInterfaceToken(ICameraService::getInterfaceDescriptor());
- remote()->transact(BnCameraService::GET_NUMBER_OF_CAMERAS,data,&reply);
- returnreply.readInt32();
- }
- //getinformationaboutacamera
- virtualstatus_tgetCameraInfo(intcameraId,
- structCameraInfo*cameraInfo){
- Parceldata,reply;
- data.writeInterfaceToken(ICameraService::getInterfaceDescriptor());
- data.writeInt32(cameraId);
- remote()->transact(BnCameraService::GET_CAMERA_INFO,data,&reply);
- cameraInfo->facing=reply.readInt32();
- cameraInfo->orientation=reply.readInt32();
- returnreply.readInt32();
- }
- //connecttocameraservice
- virtualsp<ICamera>connect(constsp<ICameraClient>&cameraClient,intcameraId)
- {
- Parceldata,reply;
- data.writeInterfaceToken(ICameraService::getInterfaceDescriptor());
- data.writeStrongBinder(cameraClient->asBinder());
- data.writeInt32(cameraId);
- remote()->transact(BnCameraService::CONNECT,data,&reply);
- returninterface_cast<ICamera>(reply.readStrongBinder());
- }
- };
- IMPLEMENT_META_INTERFACE(CameraService,"android.hardware.ICameraService");
- //----------------------------------------------------------------------
- status_tBnCameraService::onTransact(
- uint32_tcode,constParcel&data,Parcel*reply,uint32_tflags)
- {
- switch(code){
- caseGET_NUMBER_OF_CAMERAS:{
- CHECK_INTERFACE(ICameraService,data,reply);
- reply->writeInt32(getNumberOfCameras());
- returnNO_ERROR;
- }break;
- caseGET_CAMERA_INFO:{
- CHECK_INTERFACE(ICameraService,data,reply);
- CameraInfocameraInfo;
- memset(&cameraInfo,0,sizeof(cameraInfo));
- status_tresult=getCameraInfo(data.readInt32(),&cameraInfo);
- reply->writeInt32(cameraInfo.facing);
- reply->writeInt32(cameraInfo.orientation);
- reply->writeInt32(result);
- returnNO_ERROR;
- }break;
- caseCONNECT:{
- CHECK_INTERFACE(ICameraService,data,reply);
- sp<ICameraClient>cameraClient=interface_cast<ICameraClient>(data.readStrongBinder());
- sp<ICamera>camera=connect(cameraClient,data.readInt32());
- reply->writeStrongBinder(camera->asBinder());
- returnNO_ERROR;
- }break;
- default:
- returnBBinder::onTransact(code,data,reply,flags);
- }
- }
- //----------------------------------------------------------------------------
- };//namespaceandroid
[cpp] view plain copy
- constsp<ICameraService>&Camera::getCameraService()
- {
- Mutex::Autolock_l(mLock);
- if(mCameraService.get()==0){
- sp<IServiceManager>sm=defaultServiceManager();
- sp<IBinder>binder;
- do{
- binder=sm->getService(String16("media.camera"));
- if(binder!=0)
- break;
- LOGW("CameraServicenotpublished,waiting...");
- usleep(500000);//0.5s
- }while(true);
- if(mDeathNotifier==NULL){
- mDeathNotifier=newDeathNotifier();
- }
- binder->linkToDeath(mDeathNotifier);
- mCameraService=interface_cast<ICameraService>(binder);
- }
- LOGE_IF(mCameraService==0,"noCameraService!?");
- returnmCameraService;
- }
因为在这个类中实现了ICameraService的方法。
总结上面Binder机制,仅仅考虑分析Binder用法,对底层实现不进行深究,基本步骤如下:
1.定义进程间通信的接口比如这里的ICameraService;
2.在BnCameraService和BpCamaraService实现这个接口,这两个接口也分别继承于BnInterface和BpInterface;
3.服务端向ServiceManager注册Binder,客户端向ServiceManager获得Binder;
4.然后就可以实现双向进程间通信了;
通过getCameraService得到ICameraService引用后,调用ICameraService的connect方法获得ICamera引用,
- <prename="code"class="cpp">c->mCamera=cs->connect(c,cameraId);</pre>进一步跟进connect方法,这里就是BpCameraService类中connect方法的具体实现。<br>
- <prename="code"class="cpp">virtualsp<ICamera>connect(constsp<ICameraClient>&cameraClient,intcameraId)
- {
- Parceldata,reply;
- data.writeInterfaceToken(ICameraService::getInterfaceDescriptor());
- data.writeStrongBinder(cameraClient->asBinder());
- data.writeInt32(cameraId);
- remote()->transact(BnCameraService::CONNECT,data,&reply);
- returninterface_cast<ICamera>(reply.readStrongBinder());
- }</pre>在这里返回的ICamera对象,实际上应该是BpCamera对象,这里使用的是匿名Binder,前面获取CameraService的使用的有名Binder,有名Binder需要借助于ServiceManager获取Binder,而匿名Binder可以通过已经建立后的通信通道(有名Binder)获得。以上是实现Camera框架部分,具体的实现Camera相关的方法是在ICamera相关的接口,下面是给接口的定义:<prename="code"class="cpp">classICamera:publicIInterface
- {
- public:
- DECLARE_META_INTERFACE(Camera);
- virtualvoiddisconnect()=0;
- //connectnewclientwithexistingcameraremote
- virtualstatus_tconnect(constsp<ICameraClient>&client)=0;
- //preventotherprocessesfromusingthisICamerainterface
- virtualstatus_tlock()=0;
- //allowotherprocessestousethisICamerainterface
- virtualstatus_tunlock()=0;
- //passthebufferedSurfacetothecameraservice
- virtualstatus_tsetPreviewDisplay(constsp<Surface>&surface)=0;
- //passthebufferedISurfaceTexturetothecameraservice
- virtualstatus_tsetPreviewTexture(
- constsp<ISurfaceTexture>&surfaceTexture)=0;
- //setthepreviewcallbackflagtoaffecthowthereceivedframesfrom
- //previewarehandled.
- virtualvoidsetPreviewCallbackFlag(intflag)=0;
- //startpreviewmode,mustcallsetPreviewDisplayfirst
- virtualstatus_tstartPreview()=0;
- //stoppreviewmode
- virtualvoidstopPreview()=0;
- //getpreviewstate
- virtualboolpreviewEnabled()=0;
- //startrecordingmode
- virtualstatus_tstartRecording()=0;
- //stoprecordingmode
- virtualvoidstopRecording()=0;
- //getrecordingstate
- virtualboolrecordingEnabled()=0;
- //releasearecordingframe
- virtualvoidreleaseRecordingFrame(constsp<IMemory>&mem)=0;
- //autofocus
- virtualstatus_tautoFocus()=0;
- //cancelautofocus
- virtualstatus_tcancelAutoFocus()=0;
- /*
- *takeapicture.
- *@parammsgTypethemessagetypeanapplicationselectivelyturnon/off
- *onaphoto-by-photobasis.Thesupportedmessagetypesare:
- *CAMERA_MSG_SHUTTER,CAMERA_MSG_RAW_IMAGE,CAMERA_MSG_COMPRESSED_IMAGE,
- *andCAMERA_MSG_POSTVIEW_FRAME.Anyothermessagetypeswillbeignored.
- */
- virtualstatus_ttakePicture(intmsgType)=0;
- //setpreview/captureparameters-key/valuepairs
- virtualstatus_tsetParameters(constString8¶ms)=0;
- //getpreview/captureparameters-key/valuepairs
- virtualString8getParameters()const=0;
- //sendcommandtocameradriver
- virtualstatus_tsendCommand(int32_tcmd,int32_targ1,int32_targ2)=0;
- //tellthecamerahaltostoremetadataorrealYUVdatainvideobuffers.
- virtualstatus_tstoreMetaDataInBuffers(boolenabled)=0;
- };</pre><br>
- <prename="code"class="cpp"style="background-color:rgb(255,255,255);">ICamera接口有两个子类BnCamera和BpCamera,是Binder通信的两端,BpCamera提供客户端调用接口,BnCamera封装具体的实现,BnCamera也并没有真正实现ICamera相关接口而是在BnCamera子类CameraService::Client中进行实现。而在CameraService::Client类中会继续调用硬件抽象层中相关方法来具体实现Camera功能,
- 现在来缕一缕android中Camera各个类如何联系的
- 。。。。未完</pre>
- <pre></pre>
- <pre></pre>
- <pre></pre>
- <pre></pre>
- <pre></pre>
更多相关文章
- android listview 圆角的实现方案,模仿Iphone的UITableView
- android之播放多媒体文件一(播放音频)
- android输入法02:openwnn源码解析01—输入流程
- Android(安卓)HIDL学习(2) ---- HelloWorld
- 在Android里完美实现基站和WIFI定位
- UiAutomator通过ant实现快速调试
- Android编程实现连接Wifi(运用Wifi 相关 API)
- 浅谈Java中Collections.sort对List排序的两种方法
- Python list sort方法的具体使用