现在的位置: 首页 > 综合 > 正文

Android 4.0 Camera架构分析之Camera初始化

2014年02月16日 ⁄ 综合 ⁄ 共 6061字 ⁄ 字号 评论关闭

Android Camera采用C/S架构,clientserver两个独立的线程之间使用Binder通信,这已经是众所周知的了。这里将介绍Camera从设备开机,到进入相机应用是如何完成初始化工作的。

    首先既然Camera是利用binder通信,它肯定要将它的service注册到ServiceManager里面,以备后续Client引用,那么这一步是在哪里进行的呢?细心的人会发现,在frameworks\base\media\mediaserver\Main_MediaServer.cpp下有个main函数,可以用来注册媒体服务。没错就是在这里,CameraService完成了服务的注册

 

int main(int argc, char**argv) { sp<ProcessState> proc(ProcessState::self());sp<IServiceManager> sm = defaultServiceManager();LOGI("ServiceManager: %p", sm.get()); waitBeforeAdding(String16("media.audio_flinger")
);AudioFlinger::instantiate(); waitBeforeAdding(String16("media.player") );MediaPlayerService::instantiate(); waitBeforeAdding(String16("media.camera") ); CameraService::instantiate();waitBeforeAdding( String16("media.audio_policy") );AudioPolicyService::instantiate();ProcessState::self()->startThreadPool();IPCThreadState::self()->joinThreadPool();
}


 

可是我们到CameraService文件里面却找不到instantiate()这个函数,它在哪?继续追到它的一个父类BinderService

staticvoid instantiate() { publish(); }
static status_t publish() {sp<IServiceManager> sm(defaultServiceManager()); returnsm->addService(String16(SERVICE::getServiceName()), newSERVICE()); }

可以发现在publish()函数中,CameraService完成服务的注册。这里面有个SERVICE,源码中有说明 

template<typenameSERVICE>
这表示SERVICE是个模板,这里是注册CameraService,所以可以用CameraService代替

returnsm->addService(String16(CameraService::getServiceName()), newCameraService());
好了这样,Camera就在ServiceManager完成服务注册,提供给client随时使用。

Main_MediaServer主函数由init.rc在启动是调用,所以在设备开机的时候Camera就会注册一个服务,用作binder通信。

service media/system/bin/mediaserver class main user media group audio camera inetnet_bt net_bt_admin net_bw_acct drmrpc ioprio rt 4

Binder服务已注册,那接下来就看看client如何连上server端,并打开camera模块。

咱们先从cameraapp的源码入手。在onCreate()函数中专门有一个openCamera的线程

publicvoid onCreate(Bundle icicle) {

......

mCameraOpenThread.start();

}

再看看mCameraOpenThread

ThreadmCameraOpenThread = new Thread(new Runnable() {
       public void run() {
           try {
               qcameraUtilProfile("open camera");
               mCameraDevice = Util.openCamera(Camera.this,mCameraId);
               qcameraUtilProfile("camera opended");
           } catch (CameraHardwareException e) {
               mOpenCameraFail = true;
           } catch (CameraDisabledException e) {
               mCameraDisabled = true;
           }
        }
   });

继续追Util.openCamera

returnCameraHolder.instance().open(cameraId)

又来了个CameraHolder,该类用一个实例openCamera

publicsynchronized android.hardware.Cameraopen(int
cameraId)

           throwsCameraHardwareException {

   mCameraDevice= android.hardware.Camera.open(cameraId);

  returnmCameraDevice;

}

在这里就开始进入framework层了,调用frameworks\base\core\java\android\hardware\Camera.java类的open方法。

publicstatic Camera open(){

   return newCamera(i);

}

这里调用了Camera的构造函数,在看看构造函数

Camera(intcameraId){

native_setup(newWeakReference<Camera>(this), cameraId)

}

好,终于来到JNI

继续看cameraJNI文件android_hardware_camera.cpp

staticvoid android_hardware_Camera_native_setup(JNIEnv*env,
jobject thiz,
    jobject weak_this, jintcameraId)
{
    sp<Camera> camera =Camera::connect(cameraId);

   sp<JNICameraContext>context = new JNICameraContext(env, weak_this, clazz, camera);
   camera->setListener(context);

}

JNI函数里面,我们找到CameraC/S架构的客户端了,它调用connect函数向服务器发送连接请求。JNICameraContext这个类是一个监听类,用于处理底层Camera回调函数传来的数据和消息

看看客户端的connect函数有什么

sp<Camera>Camera::connect(int cameraId)
{
   LOGV("connect");
    sp<Camera> c =new Camera();
    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();
    }
    return c;
}

先看标红的第一句,通过getCameraService()函数获取一个Camera服务实例。

constsp<ICameraService>& Camera::getCameraService()
{
   if (mCameraService.get() == 0) {
       sp<IServiceManager> sm = defaultServiceManager();
       sp<IBinder> binder;
       do {
           binder = sm->getService(String16("media.camera"));
           if (binder != 0)
               break;
           LOGW("CameraService not published, waiting...");
           usleep(500000); // 0.5 s
       } while(true);
  

        mCameraService= interface_cast<ICameraService>(binder);
   }
    LOGE_IF(mCameraService==0, "noCameraService!?");
    returnmCameraService;
}

可以看出,该CameraService实例是通过binder获取的,由binder机制可以知道,该服务就是CameraService一个实例。

c->mCamera= cs->connect(c, cameraId);

然后执行服务端的connect()函数,并返回一个ICamera对象赋值给CameramCamera,服务端connect()返回的其实是它内部类client的一个实例。

sp<ICamera>CameraService::connect({

   hardware = newCameraHardwareInterface(camera_device_name);
    if(hardware->initialize(&mModule->common) != OK) {
       hardware.clear();
       return NULL;
    }

   client = newClient(this, cameraClient, hardware, cameraId, info.facing,callingPid);
    mClient[cameraId] = client;
   LOG1("CameraService::connect X");
   return client;

}

先实例化CameraHal接口hardwarehardware调用initialize()进入HAL层打开Camear驱动

status_tinitialize(hw_module_t *module)
    {
       LOGI("Opening camera %s", mName.string());
       int rc = module->methods->open(module,mName.string(),
                                      (hw_device_t **)&mDevice);

       if (rc != OK) {
           LOGE("Could not open camera %s: %d", mName.string(),rc);
           return rc;
        }
       initHalPreviewWindow();
       return rc;
    }

module->methods->open(module,mName.string(),
                                      (hw_device_t **)&mDevice)
这一句作用就是打开Camera底层驱动

hardware->initialize(&mModule->common)mModule模块是一个结构体camera_module_t,他是怎么初始化的呢?我们发现CameraService里面有个函数

voidCameraService::onFirstRef()
{
   BnCameraService::onFirstRef();

    if(hw_get_module(CAMERA_HARDWARE_MODULE_ID,
               (const hw_module_t **)&mModule) < 0
){
        LOGE("Could notload camera HAL module");
       mNumberOfCameras = 0;
    }
 
}

了解HAL层的都知道hw_get_module函数就是用来获取模块的Halstub,这里是通过CAMERA_HARDWARE_MODULE_ID 获取CameraHal层的代理stub,并赋值给mModule,后面就可通过操作mModule完成对Camera模块的控制。那么onFirstRef()函数又是何时调用的?

onFirstRef()属于其父类RefBase,该函数在强引用sp新增引用计数时调用,什么意思?就是当有sp包装的类初始化的时候调用,那么camera是何时调用的呢?可以发现在

客户端发起连接时候

sp<Camera>Camera::connect(int cameraId)
{
   LOGV("connect");
    sp<Camera> c =new Camera();
    constsp<ICameraService>& cs = getCameraService();

}

    这个时候初始化了一个CameraService实例,且用Sp包装,这个时候sp将新增计数,相应的CameraService实例里面onFirstRef()函数完成调用。
CameraService::connect
()返回client的时候,就表明客户端和服务端连接建立。Camera完成初始化,可以进行拍照和preview等动作。一个看似简单Camera初始化的过程,研究起来却也让人费劲啊。。。

下面是整个过程的时序图

抱歉!评论已关闭.