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)
{
sp<ProcessState> proc(ProcessState::self());
sp<IServiceManager> 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<IServiceManager> sm(defaultServiceManager());
return sm->addService(String16(CameraService::getServiceName()),
new CameraService(), allowIsolated);
}
...................
static void instantiate() { publish(); }
...................
};
相机服务的初始化过程首先是创建CameraService实例,然后将其注册到ServiceManager中,关于它的启动是发生在init.rc中,通过media_server来启动CameraService,具体代码如下:
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 drm
service 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.cpp
static 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应用程序代码就不分析了,下面这副图是一个简单的流程图,画得有点丑
图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<Camera>(this), cameraId);
}
}
图2-2:照相机服务请求示意图
frameworks/base/core/jni/android_hardware_Camera.cpp
static 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)
{
sp<Camera> camera = 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<JNICameraContext> 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
sp<Camera> Camera::connect(int cameraId)
{
ALOGV("connect");
sp<Camera> c = new Camera();//BnCameraClient
const sp<ICameraService>& 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<ICameraService>
{
public:
// connect to camera service
virtual sp<ICamera> connect(const sp<ICameraClient>& 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<ICamera>(reply.readStrongBinder());//BpCamera
}
};
首先将我们传递过来的Camera对象转换成IBinder类型,然后由BnCameraService去响应该连接,最后就是等待服务端返回,如果成功这里为我们生成一个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<ICameraClient> cameraClient =//(a)
interface_cast<ICameraClient>(data.readStrongBinder());
//return Client 继承BnCamera
sp<ICamera> camera = connect(cameraClient, data.readInt32());//(b)
reply->writeStrongBinder(camera->asBinder());//(c)
return NO_ERROR;
} break;
default:
return BBinder::onTransact(code, data, reply, flags);
}
}
服务端接到CONNECT命令之后开始进行一系列的类型转换,先看代码段(a)还记得之前我们传递过来的是Camera实例,Camera继承了BnCameraClient,所以在(a)中,使用Camera的Binder对象为我们生成了Camera服务代理BpCameraClient实例(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
sp<ICamera> CameraService::connect(
const sp<ICameraClient>& 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> 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<Client> 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
来源:oschina
链接:https://my.oschina.net/u/172402/blog/112639