Android的Camera架构

一 Android Camera框架

要了解AndroidCamera架构,还是得先从Android本身的架构说起。




图1 Android Architecture

从Android框架看,分为四层:应用层、应用框架层、库层、内核层。

应用层主要工作在AndroidSDK之上,利用Android提供的API进行开发,生成APK包。

应用框架层整合了Android自带各种控件和类,为应用开发提供高效、方便的API接口。这个对上实现统一的接口,对下也提供统一的标准方便各种库的移入。

库层是Android与底层硬件通信接口,它封装底层硬件接口实现该模块的具体逻辑,并以服务的形式通过Binder通讯机制暴露给应用框架。

内核层则是直接与硬件联系的一层,可以理解为设备驱动。

通过对上面框架的简要说明,我们大致明白一个应用自上而下的各个层起什么作用,这样有助于我们对代码的理解和修改。如果要做基于Androidporting工作,就要明白在哪个层次的porting,怎么porting。

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

图2 Camera Architecture

二 Android Camera架构分层及代码结构

以开源的Android 为例,Camera 架构主要分为以下几个层次

2.1应用层

Camera 的JAVA应用程序的路径:

packages/apps/Camera/src/com/android/camera/

在其中Camera.java是主要实现的文件

2.2 JNI层(Camera 的 JAVA 本地调用部分):

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

这个类是和JNI中定义的类是同一个,有些native方法通过JNI的方式调用Native代码实现具体的功能,比如startPreview、autoFocus、takePicture等。

2.3 Cameraclient层:

头文件分布以下的目录中:

frameworks/base/include/camera/

Camera底层库在以下的目录中:

frameworks/base/libs/camera/

这部分的内容被编译成库libcamera_client.so(或者libui.so),主要实现了以下几个类:

Camera---->Camera.cpp/Camera.h

CameraParameters---->CameraParameters.cpp/CameraParameters.h

ICamera---->ICamera.cpp/ ICamera.h

ICameraClient---->ICameraClient.cpp/ ICameraClient.h

ICameraService---->ICameraService.cpp/ ICameraService.h

ICamera、ICameraClient、ICameraServide三个类是按照BinderIPC通信要求的框架实现的, 用来与service端通信。

类CameraParameters接收Framework层的android.hardware.camera::Parameters类为参数, 解析与格式化所有的参数配置。

Camera是个很重要的类,它与CameraService端通过BinderIPC机制交互来实现具体功能。Cametra继承自BnCameraClient,并最终继承自ICameraClient.

2.4 CameraService层

文件分布在frameworks/base/camera/libcameraservice/这部分内容被编译成库libcameraservice.so,libcameraservice.so是Camera的服务器程序,它通过继承libcamera_client.so的类实现服务器的功能,并且与libcamera_client.so中的另外一部分内容则通过进程间通讯(即Binder机制)的方式进行通讯。

里面主要实现了两个类:

CameraService---->BnCameraService---->ICameraService

CameraService::Client---->BnCamera---->ICamera

CameraService::Client通过调用CameraHAL层来实现具体的功能。

2.5 HAL层

Libcameraservice.so::CameraService::Client类调用CameraHAL的代码实现具体的功能,CameraHAL一般实现为一个动态库libcamera.so(动态库的名字可以修改, 只需要与android.mk一致即可)。

所有java应用层中camera的功能最终会调用到HAL层这里,CameraHAL层的实现依赖于硬件, 一般通过V4L2command从linuxkernel中的cameradriver获得preview数据, 然后交给surface(overlay)显示或者保存为文件。在HAL层需要打开对应的设备文件, 并通过ioctrl访问cameradriver。Android通过这个HAL层来保证底层硬件(驱动)改变, 只需修改对应的HAL层代码,FrameWork层与JAVAAP层都不用改变。

2.6 Camera库文件分析

前面已提到Camera模块主要包含libandroid_runtime.so、libcamera_client.s0(libui.so)、libcameraservice.so和一个与Camera硬件相关的硬件库libcamera.so。其中libandroid_runtime.so、libcamera_client.s0(libui.so)是与android系统构架相关的, 不需要对进行其修改,libameraservice.so和libcamera.so则是和硬件设备相关联的,而cameralib.so实际上就是设备的linxu驱动,所以Camera设备的系统继承主要是通过移植CameraLinux驱动和修改libcameraservice.so库来完成。

Libcameraservice.so构建规则中使用宏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返回的指针操作真正的硬件设备则需完成以下步骤:

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

⑵编写一个源文件去定义CameraHardwareInterface类中声明的所有虚函数;

⑶编写Android.mk文件用于生成一个包含步骤⑵编写的源文件和其他相关文件的libcamera.so文件;

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

三 Camera的架构和代码分析

3.1 Camera的整体框架图Camera的各个库之间的结构可以用下图的表示:


图3 库结构图

在Camera系统的各个库中,libui.so位于核心的位置,它对上层的提供的接口主要是Camera类,类libandroid_runtime.so通过调用Camera类提供对JAVA的接口,并且实现了android.hardware.camera类。

libcameraservice.so是Camera的服务器程序,它通过继承libcamera_client.so(libui.so)的类实现服务器的功能,并且与libcamera_client.so(libui.so)中的另外一部分内容则通过进程间通讯(即Binder机制)的方式进行通讯。

libandroid_runtime.so和libcamera_client.so(libui.so)两个库是公用的,其中除了Camera还有其他方面的功能。

Camera部分的头文件在frameworks/base/include/ui/ 目录中,这个目录是和libmedia.so库源文件的目录frameworks/base/libs/ui/ 相对应的。

Camera主要的头文件有以下几个:

ICameraClient.h

Camera.h

ICamera.h

ICameraService.h

CameraHardwareInterface.h


图4Camera 类图

在这些头文件Camera.h提供了对上层的接口,而其他的几个头文件都是提供一些接口类(即包含了纯虚函数的类),这些接口类必须被实现类继承才能够使用。

整个Camera在运行的时候,可以大致上分成Client和Server两个部分,它们分别在两个进程中运行,它们之间使用Binder机制实现进程间通讯。这样在客户端调用接口,功能则在服务器中实现,但是在客户端中调用就好像直接调用服务器中的功能,进程间通讯的部分对上层程序不可见。

从框架结构上来看,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的Binder来实现进程间的通讯。

3.2 头文件ICameraClient.h

ICameraClient.h用于描述一个Camera客户端的接口,定义如下所示:

class ICameraClient:public IInterface

{

public:

DECLARE_META_INTERFACE(CameraClient);

virtual void shutterCallback() = 0;

virtual void rawCallback(constsp<IMemory>& picture) = 0;

virtual void jpegCallback(constsp<IMemory>& picture) = 0;

virtual void frameCallback(constsp<IMemory>& frame) = 0;

virtual void errorCallback(status_t error)= 0;

virtual void autoFocusCallback(boolfocused) = 0;

};

classBnCameraClient: public BnInterface<ICameraClient>

{

public:

virtual status_t onTransact( uint32_t code,

constParcel& data,

Parcel* reply,

uint32_t flags= 0);

};

在定义中,ICameraClient类继承IInterface,并定义了一个Camera客户端的接口,BnCameraClient继承了BnInterface<ICameraClient>,这是为基于Android的基础类Binder机制实现在进程通讯而构建的。根据BnInterface类模版的定义BnInterface<ICameraClient>类相当于双继承了BnInterface和ICameraClient。

IcameraClient这个类的主要接口是几个回调函数shutterCallback、rawCallback和jpegCallback等,它们在相应动作发生的时候被调用。作为Camera的“客户端”,需要自己实现几个回调函数,让服务器程序去“间接地”调用它们。

3.3 头文件Camera.h

Camera.h是Camera对外的接口头文件,它被实现CameraJNI的文件android_hardware_Camera.cpp所调用。Camera.h最主要是定义了一个Camera类:

classCamera : public BnCameraClient, public IBinder:: DeathRecipient

{

public:

staticsp<Camera> connect();

~Camera();

void disconnect();

status_t getStatus() { return mStatus; }

status_t setPreviewDisplay(constsp<Surface>& surface);

status_t startPreview();

void stopPreview();

status_t autoFocus();

status_t takePicture();

status_t setParameters(const String8& params);

String8 getParameters() const;

void setShutterCallback(shutter_callback cb,void *cookie);

void setRawCallback(frame_callback cb, void*cookie);

void setJpegCallback(frame_callback cb, void*cookie);

void setFrameCallback(frame_callback cb,void *cookie);

void setErrorCallback(error_callback cb,void *cookie);

void setAutoFocusCallback(autofocus_callbackcb, void *cookie);

// ICameraClient interface

virtual void shutterCallback();

virtual void rawCallback(constsp<IMemory>& picture);

virtual void jpegCallback(constsp<IMemory>& picture);

virtual void frameCallback(constsp<IMemory>& frame);

virtual void errorCallback(status_t error);

virtual void autoFocusCallback(bool focused);

//……

}

从接口中可以看出Camera类刚好实现了一个Camera的基本操作,例如播放(startPreview)、停止(stopPreview)、暂停(takePicture)等。在Camera类中connect()是一个静态函数,它用于得到一个Camera的实例。在这个类中,具有设置回调函数的几个函数:setShutterCallback、setRawCallback和setJpegCallback等,这几个函数是为了提供给上层使用,上层利用这几个设置回调函数,这些回调函数在相应的回调函数中调用,例如使用setShutterCallback设置的回调函数指针被shutterCallback所调用。

在定义中,ICameraClient类双继承了IInterface和IBinder::DeathRecipient,并定义了一个Camera客户端的接口,BnCameraClient继承了BnInterface<ICameraClient>,这是为基于Android的基础类Binder机制实现在进程通讯而构建的。事实上,根据BnInterface类模版的定义BnInterface<ICameraClient>类相当于双继承了BnInterface和ICameraClient。这是Android一种常用的定义方式。

继承了DeathNotifier类之后,这样当这个类作为IBinder使用的时候,当这个Binder即将Died的时候被调用其中的binderDied函数。继承这个类基本上实现了一个回调函数的功能。

3.4 头文件ICamera.h

ICamera.h描述的内容是一个实现Camera功能的接口,其定义如下所示:

classICamera: public IInterface

{

public:

DECLARE_META_INTERFACE(Camera);

virtual void disconnect() = 0;

virtual status_t setPreviewDisplay(constsp<ISurface>& surface) = 0;

virtual void setHasFrameCallback(bool installed) = 0;

virtual status_t startPreview() = 0;

virtual void stopPreview() = 0;

virtual status_t autoFocus() = 0;

virtual status_t takePicture() = 0;

virtual status_t setParameters(const String8& params) = 0;

virtual String8 getParameters() const = 0;

};

classBnCamera: public BnInterface<ICamera>

{

public:

virtual status_t onTransact( uint32_t code,

constParcel& data,

Parcel* reply,

uint32_tflags = 0);

};

ICamera.h描述的内容是一个实现Camera功能的接口,其定义如下所示:

在camera类中,主要定义Camera的功能接口,这个类必须被继承才能够使用。值得注意的是,这些接口和Camera类的接口有些类似,但是它们并没有直接的关系。事实上,在Camera类的各种实现中,一般都会通过调用ICamera类的实现类来完成。

3.5 头文件ICameraService .h

ICameraService.h 用于描述一个Camera的服务,定义方式如下所示:

classICameraService : public IInterface

{

public:

DECLARE_META_INTERFACE(CameraService);

virtual sp<ICamera> connect(const sp<ICameraClient>&cameraClient) = 0;

};

classBnCameraService: public BnInterface<ICameraService>

{

public:

virtual status_t onTransact( uint32_t code,

constParcel& data,

Parcel*reply,

uint32_tflags = 0);

};

由于具有纯虚函数,ICameraService 以及BnCameraService必须被继承实现才能够使用,在ICameraService只定义了一个connect()接口,它的返回值的类型是sp<ICamera>,这个ICamera是提供实现功能的接口。注意,ICameraService只有连接函数connect(),没有断开函数,断开的功能由ICamera接口来提供。

3.6 头文件CameraHardwareInterface.h

CameraHardwareInterface.h定义的是一个Camera底层的接口,这个类的实现者是最终实现Camera的。

CameraHardwareInterface 定以Camera硬件的接口,如下所示:

classCameraHardwareInterface : public virtual RefBase {

public:

virtual ~CameraHardwareInterface() { }

virtual sp<IMemoryHeap> getPreviewHeap() const = 0;

virtual status_t startPreview(preview_callback cb, void*user) = 0;

virtual void stopPreview() = 0;

virtual status_t autoFocus(autofocus_callback,

void* user) = 0;

virtual status_t takePicture(shutter_callback,

raw_callback,

jpeg_callback,

void* user)= 0;

virtual status_t cancelPicture(bool cancel_shutter,

boolcancel_raw,

boolcancel_jpeg) = 0;

virtual status_t setParameters(const CameraParameters&params) = 0;

virtual CameraParameters getParameters() const = 0;

virtual void release() = 0;

virtual status_t dump(int fd, constVector<String16>& args) const = 0;

};

使用C语言的方式导出符号:

extern"C" sp<CameraHardwareInterface> openCameraHardware();

在程序的其他地方,使用openCameraHardware()就可以得到一个CameraHardwareInterface,然后调用CameraHardwareInterface的接口完成Camera的功能。

更多相关文章

  1. C语言函数以及函数的使用
  2. Android: AIDL --- Android中的远程接口
  3. android中实现swipe的手势功能及页面拖动动画
  4. Android使用ViewFlipper实现图片切换功能
  5. Android防止内存溢出浅析/应用自动更新功能的代码实现
  6. Android Camera的接口与架构介绍
  7. Android微信端的下拉刷新功能
  8. Android 设置默认锁屏壁纸接口
  9. Android Studio 4.0 新功能之 AndroidKotlin Live Templates

随机推荐

  1. Fragment封装切换
  2. android自动化测试工具之DroidPilot
  3. Android面面观——Android事件处理下(按键
  4. Android(安卓)设计模式之面向对象的六大
  5. android 搜索框(一)
  6. 【翻译】Android安全之Linux内核篇
  7. android 退出按钮
  8. Android(安卓)Handler Message Looper机
  9. Android开发之Memory类的分析
  10. 打造开发神器—Android(安卓)Studio上的