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


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

        首先既然Camera是利用binder通信,它肯定要将它的service注册到ServiceManager里面,以备后续Client引用,那么这一步是在哪里进行的呢?细心的人会发现,在frameworksasemediamediaserverMain_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

     

     

    static void instantiate() { publish(); }
    static status_t publish() { sp<IServiceManager> sm(defaultServiceManager()); return sm->addService(String16(SERVICE::getServiceName()), new SERVICE()); }

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

     

     

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

     

     

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

     

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

     

    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

    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层了,调用frameworksasecorejavaandroidhardwareCamera.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初始化的过程,研究起来却也让人费劲啊。。。

    下面是整个过程的时序图

    转自:http://blog.chinaunix.net/uid-2630593-id-3307176.html

  • 相关阅读:
    【专题总结】数学(未完)
    如何使用SOCKS代理通过aiohttp发出请求?(How to use SOCKS proxies to make requests with aiohttp?)
    通过 alembic 重命名表列名(Model字段名)
    Supervisor使用详解
    MySQL创建数据库并设置字符集
    手动配置代理,让终端上网
    mac下镜像飞速安装Homebrew教程
    Python3.8 异步 asyncio
    PHP版本微信支付开发
    PHP对接支付宝支付接口
  • 原文地址:https://www.cnblogs.com/xuyuantao/p/3301184.html
Copyright © 2020-2023  润新知