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

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


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

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

 

[cpp]  view plain  copy
  1. int main(int argc, char** argv)  
  2. {  
  3.     sp<ProcessState> proc(ProcessState::self());  
  4.     sp<IServiceManager> sm = defaultServiceManager();  
  5.     LOGI("ServiceManager: %p", sm.get());  
  6.     waitBeforeAdding( String16("media.audio_flinger") );  
  7.     AudioFlinger::instantiate();  
  8.     waitBeforeAdding( String16("media.player") );  
  9.     MediaPlayerService::instantiate();  
  10.     waitBeforeAdding( String16("media.camera") );  
  11.     CameraService::instantiate();  
  12.     waitBeforeAdding( String16("media.audio_policy") );  
  13.     AudioPolicyService::instantiate();  
  14.     ProcessState::self()->startThreadPool();  
  15.     IPCThreadState::self()->joinThreadPool();  
  16. }  


 

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

[cpp]  view plain  copy
  1. static void instantiate() { publish(); }  

[cpp]  view plain  copy
  1. static status_t publish() {  
  2.     sp<IServiceManager> sm(defaultServiceManager());  
  3.     return sm->addService(String16(SERVICE::getServiceName()), new SERVICE());  
  4. }  


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

[cpp]  view plain  copy
  1. template<typename SERVICE>  

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

[cpp]  view plain  copy
  1. return sm->addService(String16(CameraService::getServiceName()), new CameraService());  

好了这样,Camera就在ServiceManager完成服务注册,提供给client随时使用。

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

[python]  view plain  copy
  1. service media /system/bin/mediaserver  
  2.     class main  
  3.     user media  
  4.     group audio camera inet net_bt net_bt_admin net_bw_acct drmrpc  
  5.     ioprio rt 4  

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

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

public void onCreate(Bundle icicle) {

......

mCameraOpenThread.start();

}

再看看mCameraOpenThread

Thread mCameraOpenThread = 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

return CameraHolder.instance().open(cameraId)

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

public synchronized android.hardware.Camera open(int cameraId)
            throws CameraHardwareException {

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

   return mCameraDevice;

}

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

public static Camera open(){

    return new Camera(i);

}

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

Camera(int cameraId){

native_setup(new WeakReference<Camera>(this), cameraId)

}

好,终于来到JNI了

继续看camera的JNI文件android_hardware_camera.cpp

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

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

}

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

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

sp<Camera> Camera::connect(int cameraId)
{
    LOGV("connect");
    sp<Camera> c = new Camera();
    const sp<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服务实例。

const sp<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, "no CameraService!?");
    return mCameraService;
}


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

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

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

sp<ICamera> CameraService::connect(){

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

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

}

先实例化Camera Hal接口 hardware,hardware调用initialize()进入HAL层打开Camear驱动

status_t initialize(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里面有个函数

void CameraService::onFirstRef()
{
    BnCameraService::onFirstRef();

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

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

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

客户端发起连接时候

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

}

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

下面是整个过程的时序图


  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
好的,很高兴回答你关于Android开发中的相机(Camera)学习问题。在Android开发中,相机是一个非常常见的模块,因此学习如何使用相机是非常重要的一部分。 首先,你需要在AndroidManifest.xml中声明相机权限: ```xml <uses-permission android:name="android.permission.CAMERA" /> ``` 接着,在你的Activity中,你需要获取相机的实例并启动预览: ```java private Camera mCamera; private void startCameraPreview() { try { mCamera = Camera.open(); Camera.Parameters parameters = mCamera.getParameters(); // 设置相关参数 mCamera.setParameters(parameters); // 设置预览SurfaceView mCamera.setPreviewDisplay(mSurfaceView.getHolder()); // 开启预览 mCamera.startPreview(); } catch (IOException e) { Log.e(TAG, "Error while setting camera preview", e); } } ``` 上面的代码中,我们首先获取系统相机的实例,然后获取相机参数,并设置相关参数。接着,我们将预览SurfaceView和相机绑定,最后开启预览。 当你完成相机预览后,你就可以使用相机拍照了。以下是拍照的示例代码: ```java private void takePicture() { mCamera.takePicture(null, null, new Camera.PictureCallback() { @Override public void onPictureTaken(byte[] data, Camera camera) { // 处理拍照后的数据 } }); } ``` 当你调用`takePicture()`方法时,相机会拍摄一张照片,并通过PictureCallback返回照片的数据。你可以将数据保存到文件中,或者进行进一步的处理,比如将照片显示在ImageView中。 以上就是Android开发中相机的基本使用方法。当然,相机的功能还有很多,你可以尝试更多的参数设置和拍照处理,来发掘相机的更多特性。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值