http://blog.csdn.net/u010503912/article/details/52315721

Android Camera 系统架构源码分析(1)---->Camera的初始化  http://blog.csdn.net/shell812/article/details/49424857

//------------------------------------------------------------------------------------------------------------------------

1.总体介绍
  Android Camera框架从整体上看是一个client/service架构。有两个进程,一个是client进程,可以看成AP端
,主要包括Java代码和一些native层的c/c++代码;另一个是service进程,属于服务端,是native c/c++代码,
主要负责和linux kernel中的camera driver交互,搜集linux kernel中driver层传上来的数据,并交给显示系统(surface)显示。client 和 service 进程通过Binder机制进行通信,client端通过调用service端的接口实现各个具体的功能。
  对于preview数据不会通过Binder机制从service端copy 到client端,但会通过回调函数与消息机制将preview数据的buffer地址传到client端,最终可在Java ap中操作处理preview数据。

2.调用层次划分

Package -> Framework -> JNI ->Camera.cpp -- (binder) ->CameraService ->Camera HAL -> Qcom ->Camera Driver

client端:
Package 中的 camera.java 调用Framework中的 camera.java(framework/base/core/java/android/hardware).
Framework中的 camera.java 调用 JNI层的native 函数。JNI层的调用实现在android_hardware_camera.cpp(framework/base/core/jni文件下的文件都被 编译进libandroid_runtime.so)文件中,android_hardware_camera.cpp文件中的 register_android_hardware_camera(JNIEnv *env)函数会将native函数注册到虚拟机中,以供framework层的JAVA代码调用,这些native函数通过调用 libcamera_client.so中的camera类实现具体功能。

  核心的libcamera_client.so动态库源代码位于:framework/base/core/av中,其中 Icamera,IcameraClient,IcameraService三个类按照Binder IPC通信要求的框架实现的,用来与service端通信。CameraParameters类接受framework层的 android.hardware.camera::Parameters类为参数。

service端:
service端的实现在动态库libcameraservice.so中,源代码位于:frameworks/av/services/camera。
CameraService:Client类通过调用Camera HAL层来实现具体的功能。

Camera Service 在系统启动时new了一个实例额,以“media.camera”注册到servicemanager中。在init.rc中启动多媒体服务进程。

CameraHAL层:
libcameraservice.so::CameraService::Client类调用camera HAL 的代码实现具体功能。
JAVA Ap中的功能调用最终会调用到HAL层,HAL层通过startpreview 掉到hardware/qcom/camera中的start_preview.然后就是高通这一层对底层驱动上来的数据做一些处理。从linux kernel中的camera driver得到preview数据。然后交个surface显示或者保存到文件。

//------------------------------------------------------------------------------------------------------------------------

一.Camera构架分析
Android 的Camera包含取景(preview)和拍摄照片(take picture)的功能。目前Android发布版的Camera程序虽然功能比较简单,但是其程序的架构分成客户端和服务器两个部分,它们建立在 Android的进程间通讯Binder的结构上。Android中Camera模块同样遵循Andorid的框架,如下图所示

Camera Architecture
Camera模块主要包含了libandroid_runtime.so、libui.so和libcameraservice.so等几个库文件,它们之间的调用关系如下所示:

在Camera模块的各个库中,libui.so位于核心的位置,它对上层的提供的接口主要是Camera类。
    libcameraservice.so是Camera的server程序,它通过继承libui.so中的类实现server的功能,并且与libui.so中的另外一部分内容通过进程间通讯(即Binder机制)的方式进行通讯。

libandroid_runtime.so 和libui.so两个库是公用的,其中除了Camera还有其他方面的功能。整个Camera在运行的时 候,可以大致上分成Client和Server两个部分,它们分别在两个进程中运行,它们之间使用Binder机制实现进程间通讯。这样在client调 用接口,功能则在server中实现,但是在client中调用就好像直接调用server中的功能,进程间通讯的部分对上层程序不可见。

从 框架结构上来看,源码中ICameraService.h、ICameraClient.h和ICamera.h三个类定义了MeidaPlayer的 接口和 架构,ICameraService.cpp和Camera.cpp两个文件则用于Camera架构的实现,Camera的具体功能在下层调用硬件相关的 接 口来实现。 
从Camera的整体结构上,类Camera是整个系统 核心,ICamera类提供了Camera主要功能的接口,在客户端方面调 用;CameraService是Camera服务,它通过调用实际的Camera硬件接口来实现功能。事实上,图中红色虚线框的部分都是Camera程 序的框架部分,它主要利用了Android的系统的Binder机制来完成通讯。蓝色虚线框的部分通过调用Camera硬件相关的接口完成具体的 Camera服 务功能,其它的部分是为上层的Java程序提供JNI接口。在整体结构上,左边可以视为一个客户端,右边是一个可以视为服务器,二者通过Android的 Bimder来实现进程间的通讯。

二.Camera工作流程概述

1.Camera Service的启动

①.App_main process: 进程通过AndroidRuntime调用register_jni_procs向JNI注册模块的native函数供JVM调用。

AndroidRuntime::registerNativeMethods(env, "android/hardware/Camera",

camMethods, NELEM(camMethods));

其中camMethods定义如下:

  1. static JNINativeMethod camMethods[] = {
  2. { "native_setup",
  3. "(Ljava/lang/Object;)V",
  4. (void*)android_hardware_Camera_native_setup },
  5. { "native_release",
  6. "()V",
  7. (void*)android_hardware_Camera_release },
  8. { "setPreviewDisplay",
  9. "(Landroid/view/Surface;)V",
  10. (void *)android_hardware_Camera_setPreviewDisplay },
  11. { "startPreview",
  12. "()V",
  13. (void *)android_hardware_Camera_startPreview },
  14. { "stopPreview",
  15. "()V",
  16. (void *)android_hardware_Camera_stopPreview },
  17. { "previewEnabled",
  18. "()Z",
  19. (void *)android_hardware_Camera_previewEnabled },
  20. { "setHasPreviewCallback",
  21. "(ZZ)V",
  22. (void *)android_hardware_Camera_setHasPreviewCallback },
  23. { "native_autoFocus",
  24. "()V",
  25. (void *)android_hardware_Camera_autoFocus },
  26. { "native_takePicture",
  27. "()V",
  28. (void *)android_hardware_Camera_takePicture },
  29. { "native_setParameters",
  30. "(Ljava/lang/String;)V",
  31. (void *)android_hardware_Camera_setParameters },
  32. { "native_getParameters",
  33. "()Ljava/lang/String;",
  34. (void *)android_hardware_Camera_getParameters },
  35. { "reconnect",
  36. "()V",
  37. (void*)android_hardware_Camera_reconnect },
  38. { "lock",
  39. "()I",
  40. (void*)android_hardware_Camera_lock },
  41. { "unlock",
  42. "()I",
  43. (void*)android_hardware_Camera_unlock },
  44. };

JNINativeMethod的第一个成员是一个字符串,表示了JAVA本地调用方法的名称,这个名称是在JAVA程序中调用的名称;第二个成员也是一个字符串,表示JAVA本地调用方法的参数和返回值;第三个成员是JAVA本地调用方法对应的C语言函数。

②.Mediaserver proces:进程注册了以下几个server: AudioFlinger、 MediaPlayerServer、CameraService.

  1. int main(int argc, char** argv)
  2. {
  3. sp proc(ProcessState::self());
  4. sp sm = defaultServiceManager();
  5. LOGI("ServiceManager: %p", sm.get());
  6. AudioFlinger::instantiate();
  7. MediaPlayerService::instantiate();
  8. CameraService::instantiate();
  9. ProcessState::self()->startThreadPool();
  10. IPCThreadState::self()->joinThreadPool();
  11. }

当向ServiceManager注册了CameraService服务后就可以响应client的请求了

2.client端向service发送请求

①.在java应用层调用onCreate()函数得到一个上层的Camera对象

  1. public void onCreate(Bundle icicle) {
  2. super.onCreate(icicle);
  3. Thread openCameraThread = new Thread(
  4. new Runnable() {
  5. public void run() {
  6. mCameraDevice = android.hardware.Camera.open();
  7. }
  8. }
  9. );
  10. ………………………
  11. }

②.通过Camera对象的调用成员函数,而这些成员函数会调用已向JNI注册过的native函数来调用ICamera接口的成员函数向Binder Kernel Driver发送服务请求。

③. Binder Kernel Driver接收到client的请求后,通过唤醒service的进程来处理client的请求,处理完后通过回调函数传回数据并通知上层处理已完成。

三.Camera库文件分析

上面已提到Camera模块主要包含libandroid_runtime.so、libui.so、libcameraservice.so和一个与 Camera硬件相关的底层库。其中libandroid_runtime.so、libui.so是与Android系统构架相关的不需要对其进行修 改, libcameraservice.so和Camera硬件相关的底层库则是和硬件设备相关联的,而Canera硬件相关的底层库实际上就是设备的 Linux驱动,所以Camera设备的系统集成主要通过移植Camera Linux驱动和修改libcameraservice.so库来完成。

libcameraservice.so库通过以下规则来构建:

  1. LOCAL_PATH:= $(call my-dir)
  2. #
  3. # Set USE_CAMERA_STUB for non-emulator and non-simulator builds, if you want
  4. # the camera service to use the fake camera.  For emulator or simulator builds,
  5. # we always use the fake camera.
  6. ifeq ($(USE_CAMERA_STUB),)
  7. USE_CAMERA_STUB:=false
  8. ifneq ($(filter sooner generic sim,$(TARGET_DEVICE)),)
  9. USE_CAMERA_STUB:=true
  10. endif #libcamerastub
  11. endif ifeq ($(USE_CAMERA_STUB),true)
  12. #
  13. # libcamerastub
  14. #
  15. include $(CLEAR_VARS)
  16. LOCAL_SRC_FILES:=               \
  17. CameraHardwareStub.cpp      \
  18. FakeCamera.cpp
  19. LOCAL_MODULE:= libcamerastub
  20. LOCAL_SHARED_LIBRARIES:= libui
  21. include $(BUILD_STATIC_LIBRARY)
  22. endif # USE_CAMERA_STUB
  23. #
  24. # libcameraservice
  25. #
  26. include $(CLEAR_VARS)
  27. LOCAL_SRC_FILES:=               \
  28. CameraService.cpp
  29. LOCAL_SHARED_LIBRARIES:= \
  30. libui \
  31. libutils \
  32. libcutils \
  33. libmedia
  34. LOCAL_MODULE:= libcameraservice
  35. LOCAL_CFLAGS+=-DLOG_TAG=\"CameraService\"
  36. ifeq ($(USE_CAMERA_STUB), true)
  37. LOCAL_STATIC_LIBRARIES += libcamerastub
  38. LOCAL_CFLAGS += -include CameraHardwareStub.h
  39. else
  40. LOCAL_SHARED_LIBRARIES += libcamera
  41. endif
  42. include $(BUILD_SHARED_LIBRARY)

在上面的构建规则中可以看到使用了宏USE_CAMERA_STUB决定 是否使用真的Camera,如果宏为真,则使用 CameraHardwareStub.cpp和FakeCamera.cpp构造一个假的Camera,如果为假则使用 libcamera来构造一个实际上的Camera服务。

在CameraHardwareStub.cpp中定义了CameraHardwareStub类,它继承并实现了抽象类 CameraHardwareInterface中定义的真正操作Camera设备的所有的纯虚函数。通过 openCameraHardware()将返回一个CameraHardwareInterface类的对象,但由于 CameraHardwareInterface类是抽象类所以它并不能创建对象,而它的派生类CameraHardwareStub完全实现了其父类的 纯虚函数所以openCameraHardware()返回一个指向派生类对象的基类指针用于底层设备的操作。由于CameraHardwareStub 类定义的函数是去操作一个假的Camera,故通过openCameraHardware返回的指针主要用于仿真环境对Camera的模拟操作,要想通过 openCameraHardware返回的指针操作真正的硬件设备则需完成以下步骤:

1.    将CameraHardwareInterface类中的所有纯虚函数的声明改为虚函数的声明(即去掉虚函数声明后的“= 0” );

  1. class CameraHardwareInterface : public virtual RefBase {
  2. public:
  3. virtual ~CameraHardwareInterface() { }
  4. virtual sp         getPreviewHeap() const;
  5. virtual sp         getRawHeap() const;
  6. virtual status_t    startPreview(preview_callback cb, void* user);
  7. virtual bool useOverlay() {return false;}
  8. virtual status_t setOverlay(const sp &overlay) {return BAD_VALUE;}
  9. virtual void        stopPreview();
  10. virtual bool        previewEnabled();
  11. virtual status_t    startRecording(recording_callback cb, void* user);
  12. virtual void        stopRecording();
  13. virtual bool        recordingEnabled();
  14. virtual void        releaseRecordingFrame(const sp& mem);
  15. virtual status_t    autoFocus(autofocus_callback,
  16. void* user);
  17. virtual status_t    takePicture(shutter_callback,
  18. raw_callback,
  19. jpeg_callback,
  20. void* user);
  21. virtual status_t    cancelPicture(bool cancel_shutter,
  22. bool cancel_raw,
  23. bool cancel_jpeg);
  24. virtual status_t    setParameters(const CameraParameters& params);
  25. virtual CameraParameters  getParameters() const;
  26. virtual void release();
  27. virtual status_t dump(int fd, const Vector& args) const ;
  28. };

2.    编写一个源文件去定义CameraHardwareInterface类中声明的所有虚函数,并实现openCameraHardware()函数让该函数返回一个CameraHardwareInterface类对象的指针;例如:

  1. extern "C" sp openCameraHardware()
  2. {
  3. CameraHardwareInterface realCamera;
  4. return &realCamera;
  5. }

3.    仿照其他.mk文件编写Android.mk文件用于生成一个包含步骤2编写的源文件和其他相关文件的libcamera.so文件;例如

  1. LOCAL_PATH := $(call my-dir)
  2. include $(CLEAR_VARS)
  3. LOCAL_MODULE := libcamera
  4. LOCAL_SHARED_LIBRARIES := \
  5. libutils \
  6. librpc \
  7. liblog
  8. LOCAL_SRC_FILES += MyCameraHardware.cpp
  9. LOCAL_CFLAGS +=
  10. LOCAL_C_INCLUDES +=
  11. LOCAL_STATIC_LIBRARIES += \
  12. libcamera-common \
  13. libclock-rpc \
  14. libcommondefs-rpc
  15. include $(BUILD_SHARED_LIBRARY)

4.    将宏USE_CAMERA_STUB改成false,这样生成libcameraservice.so时就会包含libcamera.so库。(注:如果 CameraHardwareInterface类的成员函数并没有直接操作硬件而是调用Camera的linux驱动来间接对硬件操作,那么包含这样的 CameraHardwareInterface类的libcamera.so库就相当于一个HAL)

上面左图中libcamera.so库直接操作Camera设备,这样相对于右图来说就相当于libcamera.so库包含了Camera驱动,而右图 则将驱动从库中分离出来并形成一层HAL这样做的好处是:移植不同型号或不同厂商的同类设备时只需修改HAL中很少代码即可。

Android 上Camera分析的更多相关文章

  1. Android上的SQLLite性能分析

    也许有人还不知道,Android 是有一些内建的 类库支持 SQL Lite 数据库的操作.他提供了一个很好的方式在 Android 上组织少量的数据.不管怎样,在使用这些类库的时候有一些陷阱是需要注 ...

  2. Android 的Camera架构介绍

    http://java-admin.iteye.com/blog/452464   第一部分 Camera概述Android的Camera包含取景器(viewfinder)和拍摄照片的功能.目前And ...

  3. Android学习十二---在android上实现图像匹配

    一.效果图及功能描述 效果图 点击ShowImg后 点击match,然后点击showmatch,可以不断点击showmatch. 主要功能描述:显示在SD卡上已经存在的图片test.jpg,根据图片在 ...

  4. 编译可在Android上运行的qemu user mode

    前言 本文在Ubuntu 64位系统上对qemu项目进行交叉编译,并且只编译与qemu user mode有关的代码. 下文中的”NDK”若无特殊说明均指”Android NDK”. 下文中”$NDK ...

  5. Android APP性能分析方法及工具

    近期读到<Speed up your app>一文.这是一篇关于Android APP性能分析.优化的文章.在这篇文章中,作者介绍他的APP分析优化规则.使用的工具和方法.我觉得值得大家借 ...

  6. 【Android】Camera 使用浅析

    Camera的简单使用浅析 由于最近工作上用到android.hardware.Camera这个类,于是简单的学习了一些基本用法. 首先注意:Camera这个类在API21以后就不推荐使用了,官方提供 ...

  7. android上的图片占用内存问题

    近日正在把ios程序移植到android上,以前没做过android的程序,于是,想当然地把ios的图片资源放到了android工程的drawable文件夹下,这些图片都是png. 程序界面也很正常. ...

  8. Android源码分析-全面理解Context

    前言 Context在android中的作用不言而喻,当我们访问当前应用的资源,启动一个新的activity的时候都需要提供Context,而这个Context到底是什么呢,这个问题好像很好回答又好像 ...

  9. Android动画原理分析

    最近在Android上做了一些动画效果,网上查了一些资料,有各种各样的使用方式,于是乘热打铁,想具体分析一下动画是如何实现的,Animation, Animator都有哪些区别等等. 首先说Anima ...

随机推荐

  1. Spring Boot MongoDB JPA 简化开发

    使用SpringBoot提供的@Repository接口,可以完成曾经需要大量代码编写和配置文件定制工作.这些以前让新手程序员头疼,让有经验的程序员引以为傲的配置,由于框架的不断完善,变得不那么重要, ...

  2. HTML 网页中以超链接的方式调用iphone 手机的app

    2011-11-13 14:36:33|  分类: 随笔 |  标签:iphone  调用iphone手机app  |举报|字号 订阅     <1>. 调用iphone 手机地图APP的 ...

  3. 第一百九十节,jQuery,编辑器插件

    jQuery,编辑器插件 学习要点: 1.编辑器简介 2.引入 uEditor 编辑器(Editor),一般用于类似于 word 一样的文本编辑器,只不过是编辑为 HTML 格式的.分类纯 JS 类型 ...

  4. JavaScript 是脚本语言

    JavaScript 是一种轻量级的编程语言. JavaScript 是可插入 HTML 页面的编程代码. JavaScript 插入 HTML 页面后,可由所有的现代浏览器执行. JavaScrip ...

  5. 005 android jni 一个简单的报错

    在android中使用ndk开发需要使用到jni. 1. java.lang.UnsatisfiedLinkError: No implementation found for void com.fr ...

  6. Linq to SQL 语法查询(子查询 & in操作 & join )

    var 子查询 = from c in ctx.Customers                    where                        (from o in ctx.Ord ...

  7. Ant Design使用问题记录

    公司的测试管理平台前端使用的是Ant Design of React框架,后台使用的是python,数据库用的是mysql.没有参与前期的开发,听说是工作了10年积累下来的一个暂且可用的管理平台,开发 ...

  8. python3----函数(join)

    今天写python 100例时,有个题目是大致是这样的:已知输入形式是1+3+2+1,要求输出形式为1+1+2+3 一开始思路是将输入的字符串用split()函数划分成数组,在对数组进行排序,再用fo ...

  9. Python2.6升级Python2.7

    Python2.6升级2.7 由于Centos6系列自带的python版本为2.6.6,然而有很多应用需要依赖于python2.7来实现,所以有了这个升级的需求.升级原理很简单,无非就是下载.编译.安 ...

  10. CodeMirror:基于JavaScript的代码编辑器

    官方网站定义: http://codemirror.net/ CodeMirror is a versatile text editor implemented in JavaScript for t ...