zoukankan      html  css  js  c++  java
  • Android 5.1 Camera 架构学习之Camera初始化

    Android Camera 采用C/S架构,client 与server两个独立的线程之间(CameraService)使用Binder通信。

    一 CameraService的注册。

    1.手机开机后,会走init.rc流程,init.rc会启动MediaServer Service。

    service media /system/bin/mediaserver
        class main
        user root ####
    #   google default ####
    #   user media    ####
        group audio camera inet net_bt net_bt_admin net_bw_acct drmrpc mediadrm media sdcard_r system net_bt_stack ####
    #   google default ####
    #   group audio camera inet net_bt net_bt_admin net_bw_acct drmrpc mediadrm ####
    
        ioprio rt 4

    2.MediaServer的main函数位于frameworks/base/media/mediaserver/main_mediaserver.cpp中。

    在Main_MediaServer.cpp的main函数中,CameraService完成了注册

     1 int main(int argc __unused, char** argv)
     2 {
     3     signal(SIGPIPE, SIG_IGN);
     4     char value[PROPERTY_VALUE_MAX];
     5     bool doLog = (property_get("ro.test_harness", value, "0") > 0) && (atoi(value) == 1);
     6     pid_t childPid;
     7 ..............................
     8         sp<ProcessState> proc(ProcessState::self());
     9         sp<IServiceManager> sm = defaultServiceManager();
    10         ALOGI("ServiceManager: %p", sm.get());
    11         AudioFlinger::instantiate();
    12         MediaPlayerService::instantiate();
    13 #ifdef MTK_AOSP_ENHANCEMENT
    14         MemoryDumper::instantiate();
    15 #endif
    16         CameraService::instantiate();
    17 ......................................

    3. instantiate的实现在CameraService的父类中,

    namespace android {
    
    template<typename SERVICE>
    class BinderService
    {
    public:
        static status_t publish(bool allowIsolated = false) {
            sp<IServiceManager> sm(defaultServiceManager());
            return sm->addService(
                    String16(SERVICE::getServiceName()),
                    new SERVICE(), allowIsolated);
        }
    
        static void publishAndJoinThreadPool(bool allowIsolated = false) {
            publish(allowIsolated);
            joinThreadPool();
        }
    
        static void instantiate() { publish(); }
    
        static status_t shutdown() { return NO_ERROR; }
    
    private:
        static void joinThreadPool() {
            sp<ProcessState> ps(ProcessState::self());
            ps->startThreadPool();
            ps->giveThreadPoolName();
            IPCThreadState::self()->joinThreadPool();
        }
    };
    
    
    }; // namespace android


    可以发现在publish()函数中,CameraService完成服务的注册 。SERVICE是个模板,这里是注册CameraService,所以可用CameraService代替

      return sm->addService(String16(CameraService::getServiceName()), new CameraService());  

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

    二  client如何连上server端,并打开camera模块

    1.Client如何连接到server端。

    我们从Camera.open()开始往framework进行分析,调用frameworksasecorejavaandroidhardwareCamera.java类的open方法 。

    public static Camera open() {
    ............................................
        return new Camera(cameraId);
    .............................................
    }

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

        private int cameraInitVersion(int cameraId, int halVersion) {
            ..................................................
            return native_setup(new WeakReference<Camera>(this), cameraId, halVersion, packageName);
        }

    此后进入JNI层android_hardware_camera.cpp

    // connect to camera service
    static jint android_hardware_Camera_native_setup(JNIEnv *env, jobject thiz,
        jobject weak_this, jint cameraId, jint halVersion, jstring clientPackageName)
    {
       .......................
            camera = Camera::connect(cameraId, clientName,
                    Camera::USE_CALLING_UID);
        ......................
    
        sp<JNICameraContext> context = new JNICameraContext(env, weak_this, clazz, camera);
         ...........................
        camera->setListener(context);
        ..........................
    
    }

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

    sp<Camera> Camera::connect(int cameraId, const String16& clientPackageName,
            int clientUid)
    {
        return CameraBaseT::connect(cameraId, clientPackageName, clientUid);
    }
    template <typename TCam, typename TCamTraits>
    sp<TCam> CameraBase<TCam, TCamTraits>::connect(int cameraId,
                                                   const String16& clientPackageName,
                                                   int clientUid)
    {
        ALOGV("%s: connect", __FUNCTION__);
        sp<TCam> c = new TCam(cameraId);
        sp<TCamCallbacks> cl = c;
        status_t status = NO_ERROR;
        const sp<ICameraService>& cs = getCameraService();
    
        if (cs != 0) {
            TCamConnectService fnConnectService = TCamTraits::fnConnectService;
            status = (cs.get()->*fnConnectService)(cl, cameraId, clientPackageName, clientUid,
                                                 /*out*/ c->mCamera);
        }
        if (status == OK && c->mCamera != 0) {
            c->mCamera->asBinder()->linkToDeath(c);
            c->mStatus = NO_ERROR;
        } else {
            ALOGW("An error occurred while connecting to camera: %d", cameraId);
            c.clear();
        }
        return c;
    }
    // establish binder interface to camera service
    template <typename TCam, typename TCamTraits>
    const sp<ICameraService>& CameraBase<TCam, TCamTraits>::getCameraService()
    {
        Mutex::Autolock _l(gLock);
        if (gCameraService.get() == 0) {
            sp<IServiceManager> sm = defaultServiceManager();
            sp<IBinder> binder;
            do {
                binder = sm->getService(String16(kCameraServiceName));
                if (binder != 0) {
                    break;
                }
                ALOGW("CameraService not published, waiting...");
                usleep(kCameraServicePollDelay);
            } while(true);
            if (gDeathNotifier == NULL) {
                gDeathNotifier = new DeathNotifier();
            }
            binder->linkToDeath(gDeathNotifier);
            gCameraService = interface_cast<ICameraService>(binder);
        }
        ALOGE_IF(gCameraService == 0, "no CameraService!?");
        return gCameraService;
    }

    此处终于获得CameraService实例了,该CameraService实例是通过binder获取的。

    再来看fnConnectService是什么,

    在Camera.cpp中,有

    CameraTraits<Camera>::TCamConnectService CameraTraits<Camera>::fnConnectService =
            &ICameraService::connect;

    这样也就是说fnConnectService就是使用CameraService调用connect,从这里开始,终于从进入了服务端的流程

    status_t CameraService::connect(
            const sp<ICameraClient>& cameraClient,
            int cameraId,
            const String16& clientPackageName,
            int clientUid,
            /*out*/
            sp<ICamera>& device) { 
    
    .........................
        status_t status = validateConnect(cameraId, /*inout*/clientUid);
    ..................................
    
    if (!canConnectUnsafe(cameraId, clientPackageName,
                                  cameraClient->asBinder(),
                                  /*out*/clientTmp)) {
                return -EBUSY;
            } 
    
            status = connectHelperLocked(/*out*/client,
                                         cameraClient,
                                         cameraId,
                                         clientPackageName,
                                         clientUid,
                                         callingPid);

      device = client;  

    return OK;
    }
    status_t CameraService::connectHelperLocked(
            /*out*/
            sp<Client>& client,
            /*in*/
            const sp<ICameraClient>& cameraClient,
            int cameraId,
            const String16& clientPackageName,
            int clientUid,
            int callingPid,
            int halVersion,
            bool legacyMode) {
    
    ....................................
                client = new CameraClient(this, cameraClient,
                        clientPackageName, cameraId,
                        facing, callingPid, clientUid, getpid(), legacyMode);
    ....................................       
        status_t status = connectFinishUnsafe(client, client->getRemote());
    ............................................
    }

    在connectHelpLocked,CameraService返回一个其实是它内部类的client——CameraClient。(注意此client是CameraService内部的CameraClient,不是Camera客户端),此client还赋值给了device,而这个device,就是在客户端CameraBase.cpp中c->mCamera,

            status = (cs.get()->*fnConnectService)(cl, cameraId, clientPackageName, clientUid,
                                                 /*out*/ c->mCamera);

    而这个c->mCamera就是每一次客户端Camera.cpp中调用一些函数(如preview/takepicture)时的mCamera,这样每一次客户端调用preview/takepicture,就直接调用的是CameraClient中的相关函数。这样就真正建立了客户端和服务端的关系。如Camera.cpp中的startPreview

    // start preview mode
    status_t Camera::startPreview()
    {
        ALOGV("startPreview");
        sp <ICamera> c = mCamera;
        if (c == 0) return NO_INIT;
        return c->startPreview();
    }

    其实直接就会调用到CameraService中CameraClient.cpp中

    // start preview mode
    status_t CameraClient::startPreview() {
        LOG1("startPreview (pid %d)", getCallingPid());
        return startCameraMode(CAMERA_PREVIEW_MODE);
    }

    2.service端(其实就是CameraClient)的初始化和运行过程。

    刚才我们知道,camera客户端与服务端的调用关系,就是camera.cpp中的函数,对应到CameraClient中的函数。下面我们再看看CameraClient的初始化过程。

    在connectFinishUnsafe中,

        status_t status = client->initialize(mModule);

    我们再来看CameraClient类的initialize函数

    status_t CameraClient::initialize(camera_module_t *module) {
        int callingPid = getCallingPid();
        status_t res;
    
        mHardware = new CameraHardwareInterface(camera_device_name);
        res = mHardware->initialize(&module->common);
    
    }

    CameraClient的初始化就是:先实例化Camera Hal接口 CameraHardwareInterface,CameraHardwareInterface调用initialize()进入HAL层打开Camera底层驱动

        status_t initialize(hw_module_t *module)
        {
            ALOGI("Opening camera %s", mName.string());
            camera_module_t *cameraModule = reinterpret_cast<camera_module_t *>(module);
            camera_info info;
            status_t res = cameraModule->get_camera_info(atoi(mName.string()), &info);
            if (res != OK) return res;
    
            int rc = OK;
            if (module->module_api_version >= CAMERA_MODULE_API_VERSION_2_3 &&
                info.device_version > CAMERA_DEVICE_API_VERSION_1_0) {
                // Open higher version camera device as HAL1.0 device.
                rc = cameraModule->open_legacy(module, mName.string(),
                                                   CAMERA_DEVICE_API_VERSION_1_0,
                                                   (hw_device_t **)&mDevice);
            } else {
                rc = CameraService::filterOpenErrorCode(module->methods->open(
                    module, mName.string(), (hw_device_t **)&mDevice));
            }
            if (rc != OK) {
                ALOGE("Could not open camera %s: %d", mName.string(), rc);
                return rc;
            }
            initHalPreviewWindow();
            return rc;
        }

    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::connect(int cameraId)
    {
        LOGV("connect");
        sp c = new Camera();
        const sp& cs = getCameraService();

    }

        这个时候初始化了一个CameraService实例,且用Sp包装,这个时候sp将新增计数,相应的CameraService实例里面onFirstRef()函数完成调用。
    CameraService::connect()即实例化CameraClient并打开驱动,返回CameraClient的时候,就表明客户端和服务端连接建立。Camera完成初始化。

    总结:Camera的初始化流程简单的说就是:

    ->先是系统注册CameraService的服务

    ->AP层调用Camera.open()

    ->Camera.java调用JNI native_setup()

    ->JNI层调用 android_hardware_Camera_native_setup

    -> HAL 客户端(Camera.cpp)调用connect与服务端(CameraService.cpp)连接,并得到CameraService中的CameraClient的一个实例

    ->服务端CameraClient的初始化,实例化Camera Hal接口 CameraHardwareInterface

    ->CameraHardwareInterface 打开Camera驱动,初始化完毕

    最终的结果就是客户端会得到一个服务端CameraService中的CameraClient的一个实例,客户端的每一个函数操作其实最终都是调用CameraClient的函数

    参考文档:

    Android 4.0 Camera架构分析之Camera初始化 http://blog.csdn.net/dnfchan/article/details/7594590

    Android 5.1 Camera Framework源码

  • 相关阅读:
    C++相关资料
    OpenCV相关资料参考
    QT-undefined reference to vtable
    QToolButton弹出菜单
    QT-信号和槽机制
    了解字符集和编码
    apache配置Directory目录权限的一些配置
    linux用户(组)及文件权限说明
    Linux下重要日志文件及查看方式
    四种常见的 POST 提交数据方式
  • 原文地址:https://www.cnblogs.com/xerrard/p/4747802.html
Copyright © 2011-2022 走看看