zoukankan      html  css  js  c++  java
  • 学习Android camera笔记 & 调用流程

    参考:http://blog.csdn.net/xingyu19871124/article/details/7750189
         http://blog.csdn.net/BonderWu/article/details/5814278
         http://blog.chinaunix.net/uid-2630593-id-3307176.html
         http://zhidao.baidu.com/question/388864295.html
         等

    注:把本文内容复制到source insight中查看效果较好

        
        
         线程与进程:子进程和父进程有不同的代码和数据空间,而多个线程则共享数据空间,每个线程有自己的执行堆栈和程序计数器为其执行上下文。
        
         Handler与线程:  其实Handler并不是开辟新线程的概念,Android主要的考虑到更新界面的问题,一般情况下,更新界面(Activity)都是在主线程中更新的,
         这样就遇到了一个问题,比方说:在下载文件时候我们需要进度条显示下载进度,界面需要更新(数据是不断变的,也就是下载的大小是不断变的,要是直接
         在主线程中更新,就会造成程序的堵塞,程序很容易崩溃,通常这样联网耗时的工作需要开辟另外一个线程的,这样就不会影响主程序了),好了,到这里联
         网操作一般都需要开辟新线程了吧。
         接下来就来说Handler了,刚刚我说了Handler不是开辟新线程,在我看来,Handler更像是主线程的秘书,是一个触发器,负责管理从子线程中得到更新的数据,
         然后在主线程中更新界面。简单说下进度条的那个:  下载了多少的数据都是在子线程中得到的,在子线程中通过Handler的sendMessage()方法发送得到的下载
         的数据,当你调用了sendMessage方法后,Handler就会回调(也就是自动调用)Handler中的 HandlerMessage方法。

         启动线程:Android启动线程和JAVA一样有两种方式,一种是直接Thread类的start方法,也就是一般写一个自己的类来继承Thread    类。
         另外一种方式其实和这个差不多啊! 那就是Runnable接口,然后把Runnable的子类对象传递给Thread类再创建Thread对象.总之都是需要创建Thread对象,
         然后调用Thread类的start方法启动线程。区别就是,一个是直接创建Thread对象,另外一个是需要implement了Runnable接口对象作为创建Thread对象的参数.    
         Runnable其实我们称为线程任务。
          第一种方式一般是这样用:
            Class MyThread extends Thread{
                  public void run(){
                   //你要实现的代码
                 }
            }
             在主线程中启动这个线程:
            public class Test{
                public static void main(String[] args){
                    new MyThread().start();//启动了我们的线程了
                }
            }
            2,第二种方式一般是这样用:
            public class MyRunnable implements Runnable{
                public void run(){
                    //你需要实现的代码
                }
            }
            在主线程中启动这个线程:
            public class Test{
                public static void main(String[] args){
                     Thread t=new Thread(new MyRunnable());//这里比第一种创建线程对象多了个任务对象
                     t.start();
                }
            }
    ---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
    cpp:
    LOGD("dyyr - log %s, %s", __FILE__, __FUNCTION__);


    打开camera/唤醒camera    大致流程途径源文件:

        Camera.java            onCreate()     log1
                            开启一个新线程,在此线程中open camera

                            mCameraOpenThread的run()
                                        log2
                            运行构造函数中的run()
                            是上述两种开启线程方法中的第一种

                            Then do something about rotation and else.
                            在onCreate()中以mCameraOpenThread.join();这句等待该线程完成它的任务
                            再开启预览线程mCameraPreviewThread.start();

                            mCameraPreviewThread的run()
                    1872                    log14

                            startPreview()
                                        log14.5
                                        mCameraDevice是在log4的位置定义的,是log5返回的一个android.hardware.Camera对象
                                        (因为log5源文件第一句:package android.hardware;)
                                        这个对象的startPreview方法声明在log5下面。481行
                                        而它在log15定义。

                                        

                                        
        Util.java            openCamera() log3            

        CameraHolder.java        open()         log4
                                                    
                                                    Applications
    ---------------------------------------------------------------------------------------------------------------------------
        Camera.java            open()         log5
        
                                                       Framework
    ---------------------------------------------------------------------------------------------------------------------------
        android_hardware_camera.cpp    
            android_hardware_Camera_native_setup()
                                        log6

            android_hardware_Camera_startPreview()
                                        log15

        Camera.cpp        connect()         log7

                        startPreview()    log16

        CameraService.cpp connect()         log8        IServiceManager.cpp        ServiceManager.java(comfirmed)
                                        log8.1
                                        log8.2

                        Client()            log8.3~8.8
                            怎么到下面的log9?
                        
                        startPreview()    log17
                        startCameraMode() log18
                        startPreviewMode()log19
                                                             JNI
    ---------------------------------------------------------------------------------------------------------------------------
                                                                 进入camera之前(开机时),camera初始化
                                                                  CameraHardwareDevice.cpp         Initialize()   log'1
    ALCameraFactory.cpp device_open()       log9 (name=0)          V4L2CameraDevice.cpp            Initialize()   log'2
                      cameraDeviceOpen()  log10

    CameraHardware.cpp  connectCamera()        log11                  V4L2Camera.cpp                Initialize()   log'3

                        startPreview()    log20
                        doStartPreview()    log21

    V4L2CameraDevice.cpp  connectDevice()    log12                  V4L2Camera.h                    WorkerThread()  log'4  上述两种开启线程方法中的第一种,但并没有run(),
                                                                                                            所以还没有真正开启线程,初始化了一个指针V4L2Camera* camera_dev
                        openCameraDev()    log13
    在这个最终打开设备文件的函数中,open()得到文件描述符后,
    用iotrl()函数做了一些配置然后返回了

    PreviewWindow.cpp        startPreview()    log22
                        onNextFrameAvailableHW()    log23
                        通过perform向mPreviewWindow窗体发送消息

                        打开camera并开启预览的流程跟到这里。

    camera.cfg
                                                             HAL
    ---------------------------------------------------------------------------------------------------------------------------
        gc0308.c
        Sys_config1.fex
                                                          Kernel
    ----------------------------------------------------------------------------------------------------------------------------------------------------------------------------
    cpp:
    LOGD("dyyr - log %s, %s", __FILE__, __FUNCTION__);


    Camera.java    

        1117        public void onCreate(Bundle icicle) {            //打开

                    ......

                    mCameraOpenThread.start();                                //  1097

                    ......

                }


        1097        Thread mCameraOpenThread = new Thread(new Runnable() {
                    public void run() {
                        try {
                            mCameraDevice = Util.openCamera(Camera.this, mCameraId);        //Util.java    267
                        }

                        .......

                    }
                 }
                 
        1532        protected void doOnResume() {                //唤醒

                    ......
                    
                    Util.openCamera(this, mCameraId);                        //Util.java    267

                    ......

                }



        1836        private void startPreview() {

                    ......

                    
                    if (mCameraPreviewThread != null) {
                            synchronized (mCameraPreviewThread) {
                                mCameraPreviewThread.notify();                      //开启预览线程
                            }
                        }

                        ......

                        
                }


    Util.java                        package/apps/.../camera

        267        CameraHolder.instance().open(cameraId);                




    CameraHolder.java                    package/apps/.../camera

        131        android.hardware.Camera.open(cameraId);            //无法自动定位,frameworks/base/core/java/android/hardware/Camera.java        264    open()
        




                                packages/apps/camera/src/com/android/camera/         -------->    Camera.apk






                                                                                                        Applications
    ---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------



    Camera.java     frameworks/base/core/java/android/hardware/Camera.java                  -------->   framework.jar

        264        public static Camera open(int cameraId) {
                    return new Camera(cameraId);
                }                                        //open函数是一个静态方法,构造一个Camera对象

        285        Camera(int cameraId) {                    //构造函数
                mShutterCallback = null;
                mRawImageCallback = null;
                mJpegCallback = null;
                mPreviewCallback = null;
                mPostviewCallback = null;
                mZoomListener = null;

                Looper looper;
                if ((looper = Looper.myLooper()) != null) {
                    mEventHandler = new EventHandler(this, looper);
                } else if ((looper = Looper.getMainLooper()) != null) {
                    mEventHandler = new EventHandler(this, looper);
                } else {
                    mEventHandler = null;
                }

                native_setup(new WeakReference<Camera>(this), cameraId);                    //310
            }


        310        private native final void native_setup(Object camera_this, int cameraId);        其对应于android_hardware_Camera.cpp的android_hardware_Camera_native_setup方法,为什么????
                                                                                        貌似是有函数会去按照camMethods数组匹配



                                                                                                        Frameworks
    ---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------


    android_hardware_camera.cpp            frameworks/base/core/jni

        458        // connect to camera service
                static void android_hardware_Camera_native_setup(JNIEnv *env, jobject thiz,
                    jobject weak_this, jint cameraId)
                {
                    sp<Camera> camera = Camera::connect(cameraId);            //无法自动定位.  Camera.cpp 128
                                                                        //Camera C/S架构的客户端调用connect函数向服务器发送连接请求,
                                                                        //这个Camera类的声明在Camera.h (android4.0\frameworks\base\include\camera)

                    if (camera == NULL) {
                        jniThrowRuntimeException(env, "Fail to connect to camera service");
                        return;
                    }

                    // make sure camera hardware is alive
                    if (camera->getStatus() != NO_ERROR) {
                        jniThrowRuntimeException(env, "Camera initialization failed");
                        return;
                    }

                    jclass clazz = env->GetObjectClass(thiz);
                    if (clazz == NULL) {
                        jniThrowRuntimeException(env, "Can't find android/hardware/Camera");
                        return;
                    }

                    // We use a weak reference so the Camera object can be garbage collected.
                    // The reference is only used as a proxy for callbacks.
                    sp<JNICameraContext> context = new JNICameraContext(env, weak_this, clazz
                , camera);

                    context->incStrong(thiz);
                    camera->setListener(context);

                    // save context in opaque field
                    env->SetIntField(thiz, fields.context, (int)context.get());
                }


    Camera.cpp        frameworks/base/libs/camera

        128        sp<Camera> Camera::connect(int cameraId)
                {
                    LOGV("connect");
                    sp<Camera> c = new Camera();
                    const sp<ICameraService>& cs = getCameraService();            //获取一个Camera服务实例,本源文件40行
                    if (cs != 0) {
                        c->mCamera = cs->connect(c, cameraId);                    //然后执行服务端的connect()函数,并返回一个ICamera对象赋值给Camera 的mCamera,
                                                                           //CameraService.cpp    185~254
                    }
                    if (c->mCamera != 0) {
                        c->mCamera->asBinder()->linkToDeath(c);
                        c->mStatus = NO_ERROR;
                    } else {
                        c.clear();
                    }
                    return c;
                }

        
        40    // establish binder interface to camera service
            const sp<ICameraService>& Camera::getCameraService()
            {
                Mutex::Autolock _l(mLock);
                if (mCameraService.get() == 0) {
                    sp<IServiceManager> sm = defaultServiceManager();                    //无法自动定位,调用的是IServiceManager.cpp(frameworks/base/libs/binder)    34
                    sp<IBinder> binder;
                    do {
                        binder = sm->getService(String16("media.camera"));            //无法自动定位,搜索符号getService,定位到ServiceManager.java   49
                        if (binder != 0)
                            break;
                        LOGW("CameraService not published, waiting...");
                        usleep(500000); // 0.5 s
                    } while(true);
                    if (mDeathNotifier == NULL) {
                        mDeathNotifier = new DeathNotifier();
                    }
                    binder->linkToDeath(mDeathNotifier);
                    mCameraService = interface_cast<ICameraService>(binder);    //mCameraService是一个ICamerService类型,
                                                                            //更加具体具体一点来讲应该是BpCameraService,因为在这个类中实现了ICameraService的方法。
                }
                LOGE_IF(mCameraService==0, "no CameraService!?");
                return mCameraService;
            }


    IServiceManager.cpp        frameworks/base/libs/binder

        34        sp<IServiceManager> defaultServiceManager()
                {
                    if (gDefaultServiceManager != NULL) return gDefaultServiceManager;
                    
                    {
                        AutoMutex _l(gDefaultServiceManagerLock);
                        if (gDefaultServiceManager == NULL) {
                            gDefaultServiceManager = interface_cast<IServiceManager>(   //得到上面要的sm,它的类型是"sp<IServiceManager>",
                                                                                     //sp<T>是android的智能指针,它持有一个T类实例,并负责在必要时释放此实例
                                ProcessState::self()->getContextObject(NULL));
                        }
                    }
                    
                    return gDefaultServiceManager;
                }


    我们有必要关注一下interface_cast,通过代码跟踪:看到它的实现
    template<typename INTERFACE>
    inline sp<INTERFACE> interface_cast(const sp<IBinder>& obj)
    {
    return INTERFACE::asInterface(obj);
    }
    通过模板替换就是:
    inline sp< IServiceManager > interface_cast(const sp<IBinder>& obj)
    {
    return IServiceManager::asInterface(obj);
    }
    看来asInterface是IServiceManager的一个成员函数,我们打开IServiceManager.cpp/
    h文件,我们并没有发现该函数,那它到底在哪儿呢,仔细观察IServiceManager.cpp
    ,发现里面有个IMPLEMENT_META_INTERFACE(ServiceManager, "android.os.IServiceManager");
    在IServiceManager.h里面发现了DECLARE_META_INTERFACE(ServiceManager);
    通过跟踪这两个宏发现DECLARE_META_INTERFACE声明了一个变量和两个函数...
    interface_cast<IServiceManager>实际上返回了一个BpServiceManager,在创建一个BpServiceManager时,有些细节还是需要注意:...




    ServiceManager.java        frameworks/base/core/java/android/os

        49    public static IBinder getService(String name) {
                    Log.d(TAG, "dyyr - getService");
                try {
                    IBinder service = sCache.get(name);          //sCache是个Hashmap<String,IBinder>,用参数name:"media.camera"get这个IBinder,
                                                                //那么,这个media.camera是源代码里配置好的还是开机后添加进去的?何时添加的?
                    if (service != null) {
                        return service;
                    } else {
                        return getIServiceManager().getService(name);
                    }
                } catch (RemoteException e) {
                    Log.e(TAG, "error in getService", e);
                }
                return null;
            }



    CameraService.cpp            frameworks/base/services/camera/libcameraservice

        185        sp<ICamera> CameraService::connect(                                //服务端connect()
                        const sp<ICameraClient>& cameraClient, int cameraId) {
                    LOGE("dyyr - CameraService.cpp connect");
                    int callingPid = getCallingPid();
                    sp<CameraHardwareInterface> hardware = NULL;                    //先实例化Camera Hal接口 hardware,
                        ......


        246            if (hardware->initialize(&mModule->common) != OK) {            //hardware调用initialize()进入HAL层打开Camear驱动, CameraHardwareDevice.cpp    52
                        hardware.clear();
                        return NULL;
                    }

                    client = new Client(this, cameraClient, hardware, cameraId, info.facing,
                callingPid);

                    mClient[cameraId] = client;
                    LOG1("CameraService::connect X");
                    return client;                                            //返回的其实是它内部类client的一个实例。
                }
                


    //Camera系统使用的是Server-Client机制,Service和Client位于不同的进程中,进程间使用Binder机制进行通信,
    //Service端实际实现相机相关的操作,Client端通过Binder接口调用Service对应的操作。
    //如下图所示


    android_hardware_camera.cpp            fremework/base/core/jni                        -------->    libandroid_runtime.so                
                                                                                                        
                                                                                                        |
                                                                                                        |
                                                                                                  ------    | --------------------------
                                                                                                 |     ---------         ---------      |
                                                                                                 |    |  Client |        | Service |-----------Binder IPC---------            
                                                                                                 |     ---------         ---------      |                          |     
                                                                                                 |            libui.so                  |                          |
                                                                                                  -----------------------------------                          |
                                                                                                                                                    ------
                                                                                                                                                    |
        Camera服务                                                                                                                                    |
    CameraService.cpp等                 frameworks/base/camera/libcameraservice/            -------->     libcameraservice.so  <------------------------------------


            (    UI 库               frameworks/base/libs/ui/camera                        -------->            libcamera_client.so        )






                                                                                                JNI
    ---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------


    CameraHardwareDevice.cpp        device/softwinner/common/hardware/camera/

        52        status_t CameraHardwareDevice::Initialize()
                {
                    F_LOG;

                    // instance V4L2CameraDevice object
                    mV4L2CameraDevice = new V4L2CameraDevice(this, mCameraID);
                    if (mV4L2CameraDevice == NULL)
                    {
                        LOGE("Failed to create V4L2Camera instance");
                        return NO_MEMORY;
                    }
                    
                    status_t res = mV4L2CameraDevice->Initialize();            //V4L2CameraDevice.cpp     71

                    ......

                }
                    

    V4L2CameraDevice.cpp        device/softwinner/common/hardware/camera/

        71        status_t V4L2CameraDevice::Initialize()
                {
                    F_LOG;

                    return V4L2Camera::Initialize();            //V4L2Camera.cpp        66
                }


    V4L2Camera.cpp        device/softwinner/common/hardware/camera/

        66        status_t V4L2Camera::Initialize()
                {
                    LOGE("dyyr - %s, %s", __FILE__, __FUNCTION__);
                    F_LOG;
                    if (isInitialized()) {
                        LOGW("%s: V4L2Camera device is already initialized: mState = %d",
                             __FUNCTION__, mState);
                        return NO_ERROR;
                    }

                    /* Instantiate worker thread object. */
                    mWorkerThread = new WorkerThread(this);                                    //V4L2Camera.h    325
                    if (getWorkerThread() == NULL) {
                        LOGE("%s: Unable to instantiate worker thread object", __FUNCTION__);
                        return ENOMEM;
                    }

                    mState = ECDS_INITIALIZED;

                    return NO_ERROR;
                }


    V4L2Camera.h        device/softwinner/common/hardware/camera/

        325        inline explicit WorkerThread(V4L2Camera* camera_dev)
                    : Thread(true),   // Callbacks may involve Java calls.                //顶层打开/唤醒Camera的流程跟到这里---------------------------未完待续
                      mCameraDevice(camera_dev),
                      mThreadControl(-1),
                      mControlFD(-1)
                {
                }

    ------------------------------------------------------------------


    下面是camera的HAL层open底层驱动的方法,没有使用传统的这一句:module->methods->open(module, mName.string(),(hw_device_t **)&mDevice),而走的是V4L2途径:


    HALCameraFactory.cpp        device/softwinner/common/hardware/camera/

        201        struct hw_module_methods_t HALCameraFactory::mCameraModuleMethods = {
                    open: HALCameraFactory::device_open                                            //    160
                };


        160        int HALCameraFactory::device_open(const hw_module_t* module,
                                                       const char* name,
                                                       hw_device_t** device)
                {
                    F_LOG;
                    /*
                     * Simply verify the parameters, and dispatch the call inside the            //只需确定参数,并调用HALCamera 实例.
                     * HALCameraFactory instance.
                     */


                    ......
                    

                    return gEmulatedCameraFactory.cameraDeviceOpen(atoi(name), device);            //    118
                }


        118        int HALCameraFactory::cameraDeviceOpen(int camera_id, hw_device_t** device)
                {
                    LOGV("%s: id = %d", __FUNCTION__, camera_id);

                    ......
                    

                    return mHardwareCameras[camera_id]->connectCamera(device);            //CameraHardware.cpp        435
                }



    CameraHardware.cpp        device/softwinner/common/hardware/camera/

        435        status_t CameraHardware::connectCamera(hw_device_t** device)
                {

                
                    ......


                    if (camera_dev != NULL) {
                        /* Connect to the camera device. */
                        res = getCameraDevice()->connectDevice();                    //V4L2CameraDevice        83
                        if (res == NO_ERROR) {
                            *device = &common;
                        }
                    }

                    return -res;
                }



    V4L2CameraDevice.cpp        device/softwinner/common/hardware/camera/

        83        status_t V4L2CameraDevice::connectDevice()
                {


                    ......


                    // open v4l2 camera device
                    int ret = openCameraDev();                                                    //448
                    if (ret != OK)
                    {
                        return ret;
                    }

                    ret = cedarx_hardware_init(2);// CEDARX_HARDWARE_MODE_VIDEO

                    ......

                    
                }


        448        int V4L2CameraDevice::openCameraDev()
                {
                    // open V4L2 device
                    Log.d(TAG, "dyyr - " + __FILE__ + ", " + __FUNCTION__);
                    mCamFd = open(mDeviceName, O_RDWR | O_NONBLOCK, 0);                            //至此完成打开底层设备全过程
                    if (mCamFd == -1)
                    {
                        LOGE("ERROR opening V4L interface: %s", strerror(errno));
                        return -1;
                    }

                    struct v4l2_input inp;
                    inp.index = mDeviceID;
                    if (-1 == ioctl (mCamFd, VIDIOC_S_INPUT, &inp))
                    {
                        LOGE("VIDIOC_S_INPUT error!\n");
                        return -1;
                    }

                    ......


                }

    --------------------------------------------------------------------------



    HAL层的配置文件camera.cfg            device/softwinner/Dimond_97HD/camera.cfg,          读取配置:  CCameraConfig.cpp,  xxx()

    下面是读取配置信息的一个例子:

    CameraHardware.cpp            device/softwinner/common/hardware/camera/

        105        status_t CameraHardware::Initialize()
                {
                    F_LOG;

                    if (mCameraConfig == NULL)
                    {
                        return UNKNOWN_ERROR;
                    }

                    initDefaultParameters();                //145

                    return NO_ERROR;
                }


        145        void CameraHardware::initDefaultParameters()
                {
                

                    ......


                    if (mCameraConfig->cameraFacing() == CAMERA_FACING_BACK)                            //根据配置信息设置XX
                    {
                        p.set(CameraHardware::FACING_KEY, CameraHardware::FACING_BACK);
                        LOGV("%s: camera is facing %s", __FUNCTION__, CameraHardware::FACING_BACK
                );

                    }
                    else
                    {
                        p.set(CameraHardware::FACING_KEY, CameraHardware::FACING_FRONT);
                        LOGV("%s: camera is facing %s", __FUNCTION__, CameraHardware::
                FACING_FRONT);

                    }
                    
                    p.set(CameraHardware::ORIENTATION_KEY, 0);


                    ......


                }






                                                                                                        HAL
    ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------



    gc0308.c                        drivers/media/video/sun4i_csi/device/gc0308.c






    配置文件Sys_config1.fex        Tools/pack/Chips/Sun4i/Configs/Crane/Dimod/Sys_config1.fex,  读取函数:        ????????




                                                                                                        Kernel
    ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------


  • 相关阅读:
    【前端大神面考面试官系列】入门Vue全家桶
    【综合篇】浏览器的工作原理:浏览器幕后揭秘
    【星云测试】开发者测试(2)-采用精准测试工具对J2EE Guns开发框架进行测试
    【星云测试】开发者测试(3)-采用精准测试工具对springcloud微服务应用进行穿透测试
    【星云测试】开发者测试(4)-采用精准测试工具对dubbo微服务应用进行测试
    【星云测试】精准测试的软件产品质量效率变化分析
    巧用location.hash保存页面状态
    全面解析ASP.NET MVC模块化架构方案
    在多线程编程中lock(string){...}隐藏的机关
    注释是恶魔,请不要再写一行注释
  • 原文地址:https://www.cnblogs.com/yiru/p/2801615.html
Copyright © 2011-2022 走看看