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源码

  • 相关阅读:
    Maidsafe-去中心化互联网白皮书
    The Top 20 Cybersecurity Startups To Watch In 2021 Based On Crunchbase
    Top 10 Blockchain Security and Smart Contract Audit Companies
    The 20 Best Cybersecurity Startups To Watch In 2020
    Blockchain In Cybersecurity: 11 Startups To Watch In 2019
    004-STM32+BC26丨260Y基本控制篇(阿里云物联网平台)-在阿里云物联网平台上一型一密动态注册设备(Android)
    涂鸦开发-单片机+涂鸦模组开发+OTA
    000-ESP32学习开发-ESP32烧录板使用说明
    03-STM32+Air724UG远程升级篇OTA(阿里云物联网平台)-STM32+Air724UG使用阿里云物联网平台OTA远程更新STM32程序
    03-STM32+Air724UG远程升级篇OTA(自建物联网平台)-STM32+Air724UG实现利用http/https远程更新STM32程序(TCP指令,单片机程序检查更新)
  • 原文地址:https://www.cnblogs.com/xerrard/p/4747802.html
Copyright © 2011-2022 走看看