源代码版本:allwinner 4.0.4

frameworks代码:

frameworks/base/core/java/android/hardware/Camera.java

JNI层代码:

frameworks/base/core/jni/android_hardware_Camera.cpp

client端代码:

frameworks/base/libs/camera/

server端代码:

frameworks/base/services/camera/libcameraservice/

HAL层代码:

device/softwinner/common/hardware/camera/

camera配置文件:

system/etc/ camera.cfg


先从应用程序open camera分析,其调用流程如下图:


图中,JNI的Camera::connect函数通过跨进程调用,服务端CameraService会创建Client实体BnCamera, 并且经过binder转换,返回给JNI connet函数一个BpCamera代理,有了这个代理,就可以远程调用CameraService内嵌类client的方法,如startPreview,autoFocus等等;

并且,Camera::connect将Camera对象作为参数传递给服务端,Camera类继承自BnCameraClient,所以JNI 端Camera自身也创建了BnCameraClient实体,跨进程后,CameraService获得其代理BpCameraClient,有了这个代理,服务端就可以回调Camera端的notifyCallback,dataCallback,dataCallbackTimestamp等方法。在这种情景下,可以把CameraService视为客户端,而Camera则为服务端。


framework层的调用流程大概就如上所述,HAL层是厂商自己实现的,不同方案代码结构各有不同,这里分析的是allwinner的源代码。接着以startPreview为例子,看framework层是如何调用HAL层的。调用流程如下图所示:



对上述图中简要说明几点:

1. framework的几个callback函数在构造函数初始化时候就已经注册到了HAL中,以实现HAL层有数据时候回调framework, 最终framework回调app中的注册函数

2.CameraHardware类在初始化时候开启了DoCommandThread和DoAutoFocusThread线程,用来监听上层的命令和动作,前者监听如设置摄像头的白光平衡,曝光度,快门模式等;后者用来监听自动对焦命令。

3.doStartPreview最终会调用V4L2Camera类的startWorkerThread来启动线程,该线程实现方法在V4L2CameraDevice类的inWorkerThread函数。该函数首先调用ioctl(mCamFd, VIDIOC_DQBUF, buf)获取图像数据,并将数据进行格式转换和大小缩放。最后用OSAL_Queue方法将数据入队列并发出通知信号。

4.V4L2CameraDevice类的previewThread线程收到信号,调用onNextFrameCB,回调framwork函数将数据返回上层;并调用onNextFramePreview将数据在窗口中进行预览,这就是打开摄像头看到的预览图像。

其他流程如takePicture,startRecording等和上述差不多,下面给出takePicture的流程图,其它不再重述。



最后看应用层调用takePicture拍照时候的数据回调过程。

应用层拍照的调用函数是camera.takePicture(shutterCallback, rawCallback, jpegCallback);

shutterCallback类要实现Camera.ShutterCallback接口;rawCallback, jpegCallback类要实现Camera.PictureCallback接口,他们的一般形式如下:

//返回照片的JPEG格式的数据      private JpegCallback jpegCallback = new PictureCallback(){        public void onPictureTaken(byte[] data, Camera camera) {                Parameters ps = camera.getParameters();                        if(ps.getPictureFormat() == PixelFormat.JPEG){                          //存储拍照获得的图片                              try {                 String path = "/sdcard/"+System.currentTimeMillis()+".jpg";                    File file = new File(path);                if(!file.exists())                    file.createNewFile();                FileOutputStream fos = new FileOutputStream(file);                fos.write(data);                fos.close();                  } catch (Exception e) {                e.printStackTrace();            }                    //将图片交给Image程序处理                                   Uri uri = Uri.fromFile(new File(path));                                   Intent intent = new Intent();                                        intent.setAction("android.intent.action.VIEW");                                       intent.setDataAndType(uri, "image/jpeg");                                       startActivity(intent);                            }               }    };

//快门按下的时候onShutter()被回调private ShutterCallback shutterCallback = new ShutterCallback(){    public void onShutter() {        if(tone == null)            //发出提示用户的声音            tone = new ToneGenerator(AudioManager.STREAM_MUSIC, ToneGenerator.MAX_VOLUME);        tone.startTone(ToneGenerator.TONE_PROP_BEEP2);    }};


rawCallback则为返回未压缩的数据,一般用不上。

其framework层的回调过程如下图:


前面已经分析,hal层取得数据后回调了cameraservice的dataCallback方法和notifyCallback方法;经过binder跨进程,回调Camera端的对应方法。

1. 在JNI中,包含了一个内部类JNICameraContext,其继承自CameraListener并实现了其notify,postData和postDataTimestamp方法。在camera初始化的时候android_hardware_Camera_native_setup方法中就已经为mListener赋值了一个JNICameraContext对象。Camera类就是通过listener->postData,listener->notify等方法调用JNICameraContext类的实现方法;JNICameraContext用env->SetByteArrayRegion(obj, 0, size, data)创建空间保存压缩过的JPEG格式图片,再通过CallStaticVoidMethod回调framework中Camera.java中的方法。

2. 在Camera.java中通过EventHandler类的handleMessage来处理JNI回调的方法,swith根据参数的不同,回调APP中相应的方法,而这些方法正是是APP当初在takePicture时候传进来的。

通过上述流程就实现了数据从HAL层到APP层的回调过程。


更多相关文章

  1. 浅谈Java中Collections.sort对List排序的两种方法
  2. 箭头函数的基础使用
  3. Python技巧匿名函数、回调函数和高阶函数
  4. Python list sort方法的具体使用
  5. python list.sort()根据多个关键字排序的方法实现
  6. android 实现代码关机
  7. Android(安卓)BaseWebLoad组件使用及与js方法互调
  8. Android(安卓)Device Monitor工具的使用
  9. Android7 增加双以太网eth1的支持

随机推荐

  1. 我家云/粒子云Rockchip RK3328将Android
  2. Android(安卓)Intent传递对象的两种方法(
  3. Android之TextView实现文字过长时省略部
  4. android 读取文件相关
  5. android语言三
  6. Android.Could not find *.apk in androi
  7. 在eclipse里卸载已安装的插件[例如Androi
  8. GreenDao 3.3.0 增删改查的使用(三)
  9. Android(安卓)Room牛刀小试
  10. Android(安卓)流式布局