Camera子系统采用C/S架构,客户端和服务端在两个不同的进程当中,它们使用android中的binder机制进行通信,本系列文章将从Android Camera应用程序到硬件抽象的实现一步一步对照相机系统进行分析,首先从CameraService初始化过程着手,然后从上层APP打开照相机->进行preview->拍照以及聚焦等功能的实现全面的学习照相机子系统
1 CameraService初始化过程
frameworks/av/media/mediaserverMain_mediaserver.cpp,
CameraService在MediaServer中初始化,下面代码是MediaServer的main函数,在该函数中初始化照相机服务
int main(int argc, char** argv){ spproc(ProcessState::self()); sp sm = defaultServiceManager(); ................. CameraService::instantiate(); ............ IPCThreadState::self()->joinThreadPool();}
CameraService中的instantiate方法用来创建CameraService实例,并进行相应的初始化,这个函数定义在它的父类BinderService中:frameworks/native/include/binder/BinderService.h,替换之后见如下代码:
class BinderService{public: static status_t publish(bool allowIsolated = false) { sp相机服务的初始化过程首先是创建CameraService实例,然后将其注册到ServiceManager中,关于它的启动是发生在init.rc中,通过media_server来启动CameraService,具体代码如下:sm(defaultServiceManager()); return sm->addService(String16(CameraService::getServiceName()), new CameraService(), allowIsolated); } ................... static void instantiate() { publish(); } ...................};
system/rootdir/init.rc
service servicemanager /system/bin/servicemanager class core user system group system critical onrestart restart zygote onrestart restart media onrestart restart surfaceflinger onrestart restart drmservice media /system/bin/mediaserver class main user media group audio camera inet net_bt net_bt_admin net_bw_acct drmrpc ioprio rt 4在cameraService注册以及启动过程中cameraService自身会执行一些初始化的工作,主要涉及到如下工作
frameworks/av/services/camera/libcameraservice/CameraService.cppstatic CameraService *gCameraService;CameraService::CameraService():mSoundRef(0), mModule(0){ ALOGI("CameraService started (pid=%d)", getpid()); gCameraService = this;}void 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 {/*最大支持两个摄像头*/ 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++) { setCameraFree(i); } }}
在上述初始化代码中,先通过调用HAL硬件抽象层库,获取支持的摄像头个数并保存到mNumberOfCameras
2 应用程序链接相机服务过程
在camera应用程序启动的时候首先会和CameraService建立连接,camera应用程序代码就不分析了,下面这副图是一个简单的流程图,画得有点丑
![](http://static.oschina.net/uploads/space/2013/0309/134839_5cfO_172402.png)
图2-1:照相机应用程序启动流程图
public class Camera { public static Camera open(int cameraId) { return new Camera(cameraId); } Camera(int cameraId) { ................. Looper looper; if ((looper = Looper.myLooper()) != null) { mEventHandler = new EventHandler(this, looper); } else if ((looper = Looper.getMainLooper()) != null) { mEventHandler = new EventHandler(this, looper); } else { mEventHandler = null; } native_setup(new WeakReference(this), cameraId); }}
![](http://static.oschina.net/uploads/space/2013/0309/135139_Gb1a_172402.png)
图2-2:照相机服务请求示意图
接下来按照上面5个步骤来分析具体的源码,其中地一个步骤的源码在上一步中已解释(2)Camera open(int cameraId)方法调用native_setup本地方法,其中native_setup本地方法在JNI层被注册成如下方法:
frameworks/base/core/jni/android_hardware_Camera.cppstatic JNINativeMethod camMethods[] = {{ "native_setup","(Ljava/lang/Object;I)V", (void*)android_hardware_Camera_native_setup },/*通过Camera.cpp连接CameraService*/ …...};
(3)native_setup函数通过JNI调用android_hardware_Camera_native_setup函数,该函数的实现如下://通过android_hardware_Camera_native_setup请求CameraService
static void android_hardware_Camera_native_setup(JNIEnv *env, jobject thiz,jobject weak_this, jint cameraId){ spcamera = Camera::connect(cameraId); if (camera == NULL) { jniThrowRuntimeException(env, "Fail to connect to camera service"); return; } // make sure camera hardware is alive 还记得前面的初始化? if (camera->getStatus() != NO_ERROR) { jniThrowRuntimeException(env, "Camera initialization failed"); return; } jclass clazz = env->GetObjectClass(thiz); if (clazz == NULL) { jniThrowRuntimeException(env, "Can't find android/hardware/Camera"); return; } // We use a weak reference so the Camera object can be garbage collected. // The reference is only used as a proxy for callbacks. sp context = new JNICameraContext(env, weak_this, clazz, camera); context->incStrong(thiz); camera->setListener(context); //将这一步骤返回的BpCameraClient返回到JAVA应用程序框架 // save context in opaque field env->SetIntField(thiz, fields.context, (int)context.get());}
(4)android_hardware_Camera_native_setup通过调用Camera::connect(int cameraId)函数请求连接服务。frameworks/av/camera/camera.cpp
spCamera::connect(int cameraId){ ALOGV("connect"); sp c = new Camera();//BnCameraClient const sp & cs = getCameraService();//return BpCameraService if (cs != 0) {//Used for processing all kinds of events c->mCamera = cs->connect(c, cameraId);//return } if (c->mCamera != 0) { c->mCamera->asBinder()->linkToDeath(c); c->mStatus = NO_ERROR; } else { c.clear(); } return c;}
(5)Camera::connect(int cameraId)函数首先向ServiceManager获取Camera服务信息,并生成CameraService服务代理BpCameraService,然后通过Binder通信发送CONNECT命令,当BnCameraService收到CONNECT命令后调用CameraService的connect()成员函数来做相应的处理,接下来我们就分析CameraService的connect()成员函数,注意在这一步骤中首先new了一个Camera本地实例,这个Camera类是BnCameraClient的子类,在调用BpCameraService::connect的时候我们将新生成的Camera做为参数传递给了CameraService.我们先来看BpCameraService的connect函数
class BpCameraService: public BpInterface首先将我们传递过来的Camera对象转换成IBinder类型,然后由BnCameraService去响应该连接,最后就是等待服务端返回,如果成功这里为我们生成一个BpCamera实例,怎么来的下面继续分析,接收服务命令的代码段如下:{public: // connect to camera service virtual sp connect(const sp & cameraClient, int cameraId) { Parcel data, reply; data.writeInterfaceToken(ICameraService::getInterfaceDescriptor()); data.writeStrongBinder(cameraClient->asBinder());//转换成IBinder类型 data.writeInt32(cameraId); remote()->transact(BnCameraService::CONNECT, data, &reply); return interface_cast (reply.readStrongBinder());//BpCamera }};
status_t BnCameraService::onTransact(uint32_t code, const Parcel& data, Parcel* reply, uint32_t flags){ switch(code) { case CONNECT: { CHECK_INTERFACE(ICameraService, data, reply);// sp服务端接到CONNECT命令之后开始进行一系列的类型转换,先看代码段(a)还记得之前我们传递过来的是Camera实例,Camera继承了BnCameraClient,所以在(a)中,使用Camera的Binder对象为我们生成了Camera服务代理BpCameraClient实例cameraClient =//(a) interface_cast (data.readStrongBinder()); //return Client 继承BnCamera sp camera = connect(cameraClient, data.readInt32());//(b) reply->writeStrongBinder(camera->asBinder());//(c) return NO_ERROR; } break; default: return BBinder::onTransact(code, data, reply, flags); }}
(b)将生成的BpCameraClient对象作为参数打包到CameraService的connect()函数中,至于这个connect函数做了什么,先不管.先看(c)
(c)将在(b)中返回的实例对象以IBinder的形式返回,现在再回到BpCameraService::connect函数的最后一句return interface_cast<ICamera>(reply.readStrongBinder()),是不是明白了?如果在(c)中成功创建了一个Client实例对象,(Client是BnCamera的子类),那么在BpCameraService::connect函数中是不是会为我们返回一个BpCamera对象?yes!为了验证我们来分析CameraService的connect()成员函数frameworks/av/services/camera/libcameraservice/CameraService.cpp
spCameraService::connect( const sp & cameraClient, int cameraId) { int callingPid = getCallingPid(); LOG1("CameraService::connect E (pid %d, id %d)", callingPid, cameraId); if (!mModule) {/*在服务初始化的时候就已经获得了*/ ALOGE("Camera HAL module not loaded"); return NULL; } sp client; if (cameraId < 0 || cameraId >= mNumberOfCameras) { ALOGE("CameraService::connect X (pid %d) rejected (invalid cameraId %d).",callingPid, cameraId); return NULL; } char value[PROPERTY_VALUE_MAX]; /*策略相关*/ property_get("sys.secpolicy.camera.disabled", value, "0"); if (strcmp(value, "1") == 0) { // Camera is disabled by DevicePolicyManager. ALOGI("Camera is disabled. connect X (pid %d) rejected", callingPid); return NULL; } Mutex::Autolock lock(mServiceLock); /*这是CameraService类中的一个成员变量是用来记录摄像头设备的,并且 *它是一个数组wp mClient[MAX_CAMERAS];每一个设备都对应一个Client */ if (mClient[cameraId] != 0) {//第一次来的是应该是为空的,所以不会走这条分支 client = mClient[cameraId].promote(); if (client != 0) { if (cameraClient->asBinder() == client->getCameraClient()->asBinder()) { LOG1("CameraService::connect X (pid %d) (the same client)", callingPid); return client; } else { ALOGW("CameraService::connect X (pid %d) rejected (existing client).",callingPid); return NULL; } } mClient[cameraId].clear(); } if (mBusy[cameraId]) {/*如果这设备ID处于忙状态*/ ALOGW("CameraService::connect X (pid %d) rejected" " (camera %d is still busy).", callingPid, cameraId); return NULL; } /*这个结构是硬件抽象范畴的,里面包含了一些基本信息 * 其中facing描述前置还是后置 * orientation 用来描述image方向 * device_version用来描述HAL的版本 */ struct camera_info info; if (mModule->get_camera_info(cameraId, &info) != OK) { ALOGE("Invalid camera id %d", cameraId); return NULL; } int deviceVersion; if (mModule->common.module_api_version == CAMERA_MODULE_API_VERSION_2_0) { deviceVersion = info.device_version; } else { deviceVersion = CAMERA_DEVICE_API_VERSION_1_0; } /*根据HAL不同API的版本创建不同的client实例,在之前版本中不是这样的,这是4.2的变化*/ switch(deviceVersion) { case CAMERA_DEVICE_API_VERSION_1_0: client = new CameraClient(this, cameraClient, cameraId,info.facing, callingPid, getpid()); break; case CAMERA_DEVICE_API_VERSION_2_0://for 4.2 client = new Camera2Client(this, cameraClient, cameraId, info.facing, callingPid, getpid()); break; default: ALOGE("Unknown camera device HAL version: %d", deviceVersion); return NULL; } /*初始化camera_module_t *module*/ if (client->initialize(mModule) != OK) { return NULL; } cameraClient->asBinder()->linkToDeath(this); //最后将创建的CameraClient或Camera2Client实例保存到mClient[MAX_CAMERAS]数组当中去 //mClient[MAX_CAMERAS]数组是CameraService类中的成员变量 mClient[cameraId] = client;//every camera is a Client class LOG1("CameraService::connect X (id %d, this pid is %d)", cameraId, getpid()); return client;/*最后返回*/}
首先通过该函数我们可以验证上面的(c)观点,通过CameraService生成CameraService::Client服务代理BpCamera,下面看看Client类之间的关系图
图2-2:照相机服务请求示意图2