源代码版本: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分析,其调用流程如下图:

Android Camera架构分析_第1张图片

图中,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层的。调用流程如下图所示:

Android Camera架构分析_第2张图片


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

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的流程图,其它不再重述。

Android Camera架构分析_第3张图片


最后看应用层调用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层的回调过程如下图:

Android Camera架构分析_第4张图片

前面已经分析,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. 通过ddmlib杀死某个android进程的方法
  2. Android之 inflate() 方法总结
  3. android 系统数据库
  4. android ListView 刷新数据,加载时遇到的数组越界问题
  5. Android读取服务器图片的三种方法
  6. android播放本地工程里的音乐和视频的方法
  7. ActionBar的一些使用方法
  8. H5调用原生APP的js方法

随机推荐

  1. Android跨进程通信IPC之7——Binder相关
  2. Android实现头像上传
  3. Android跨进程通信IPC之14——其他IPC方
  4. Android安装、卸载、打开代码
  5. Android(安卓)初体验
  6. android 4.4.2 默认打开wifi
  7. Android跨进程通信IPC之4——AndroidIPC
  8. Android(安卓)笔记
  9. Android(安卓)- 直线(line)画法
  10. [置顶] Android(安卓)开发教程 (包括全部