在阅读SurfaceFlinger HardwareComposer以及gralloc相关代码的过程中,我们经常会遇到native_handle private_handle_t ANativeWindowBuffer ANativeWindow GraphicBuffer Surface等等一系列和memory相关的struct和class,他们相互之间到底是什么区别,又有什么联系呢?本文从struct/class的结构角度分析下上述类型之间的关联.

概括来说,native_handle private_handle_t ANativeWindowBuffer GraphicBuffer这四个struct/class所描述的是一块memory,而ANativeWindow 和Surface所描述的是一系列上述memeory的组合和对buffer的操作方法.有的struct/class在比较低的level使用,和平台相关,而另外一些在比较高的level使用,和平台无关,还有一些介于低/高level之间,用以消除平台相关性,让Android可以方便的运行在不同的平台上.

我们依次来看下上述struct/class的定义:

1. native_handle

system/core/include/cutils/native_handle.h

  1. typedef struct native_handle
  2. {
  3. int version;        /* sizeof(native_handle_t) */
  4. int numFds;         /* number of file-descriptors at &data[0] */
  5. int numInts;        /* number of ints at &data[numFds] */
  6. int data[0];        /* numFds + numInts ints */
  7. } native_handle_t;

native_handle/native_handle_t只是定义了一个描述buffer的结构体原型,这个原型是和平台无关的,方便buffer在各个进程之间传递,注意成员data是一个大小为0的数组,这意味着data指向紧挨着numInts后面的一个地址.我们可以把native_handle_t看成是一个纯虚的基类.

一般来说,我们描述一块buffer,需要知道它在kernel中对应的fd,虚拟地址/物理地址,offset,size等等信息,后面我们在private_handle_t中就可以看到这些字段.
   
android的gralloc模块负责从fb设备或者gpu中分配meomory,所以我们在gralloc中就可以找到native_handle的具体实现,gralloc中对buffer的描述就和具体的平台相关了,我们以aosp中最基本的gralloc为例,来看下gralloc中对native_handle是如何使用的.

2.private_handle_t

hardware/libhardware/modules/gralloc/gralloc_priv.h

  1. #ifdef __cplusplus
  2. //在c++编译环境下private_handle_t继承于native_handle
  3. struct private_handle_t : public native_handle {
  4. #else
  5. //在c编译环境下,private_handle_t的第一个成员是native_handle类型,其实和c++的继承是一个意思,
  6. //总之就是一个指向private_handle_t的指针同样也可以表示一个指向native_handle的指针.
  7. struct private_handle_t {
  8. struct native_handle nativeHandle;
  9. #endif
  10. // file-descriptors
  11. int     fd;
  12. // ints
  13. int     magic;
  14. int     flags;
  15. int     size;
  16. int     offset;
  17. // 因为native_handle的data成员是一个大小为0的数组,所以data[0]其实就是指向了fd,data[1]指向magic,以此类推.
  18. // 上面提到我们可以把native_handle看成是一个纯虚的基类,那么在private_handle_t这个派生类中,numFds=1 numInts=4.
  19. ...
  20. }

gralloc分配的buffer都可以用一个private_handle_t来描述,同时也可以用一个native_handle来描述.在不同的平台的实现上,private_handle_t可能会有不同的定义,所以private_handle_t在各个模块之间传递的时候很不方便,而如果用native_handle的身份来传递,就可以消除平台的差异性.在HardwareComposer中,由SurfaceFlinger传给hwc的handle即是native_handle类型,而hwc作为平台相关的模块,他需要知道native_handle中各个字段的具体含义,所以hwc往往会将native_handle指针转化为private_handle_t指针来使用.

3. buffer_handle_t

标题中并没有提到这个类型,因为这个类型实在是太简单了,我们看code

system/core/include/system/window.h

  1. typedef const native_handle_t* buffer_handle_t;

在window.h中又把指向native_handle_t的指针define为buffer_handle_t,

sturct native_handle

native_handle_t

struct private_handle_t
这三个类型可以看作是同一个东西,而buffer_handle_t则是指向他们的指针.

那么android是如何使用这些struct的,gralloc分配的buffer如何和android联系起来呢?
我们继续来看window.h

4. ANativeWindowBuffer和ANativeWindow

在具体分析ANativeWindowBuffer和ANativeWindow之前,我们先来看下和这两个类型都相关的另外一个结构体android_native_base_t

system/core/include/system/window.h

  1. typedef struct android_native_base_t
  2. {
  3. /* a magic value defined by the actual EGL native type */
  4. int magic;
  5. /* the sizeof() of the actual EGL native type */
  6. int version;
  7. void* reserved[4];
  8. /* reference-counting interface */
  9. void (*incRef)(struct android_native_base_t* base);
  10. void (*decRef)(struct android_native_base_t* base);
  11. } android_native_base_t;

incRef和decRef是为了把派生类和android所有class的老祖宗RefBase联系起来所预留的函数指针,在后面我们在会看到指针具体会指向哪些函数.

  1. typedef struct ANativeWindowBuffer
  2. {
  3. #ifdef __cplusplus
  4. ANativeWindowBuffer() {
  5. // ANDROID_NATIVE_BUFFER_MAGIC的值是"_bfr"
  6. common.magic = ANDROID_NATIVE_BUFFER_MAGIC;
  7. common.version = sizeof(ANativeWindowBuffer);
  8. memset(common.reserved, 0, sizeof(common.reserved));
  9. }
  10. // Implement the methods that sp<ANativeWindowBuffer> expects so that it
  11. // can be used to automatically refcount ANativeWindowBuffer's.
  12. // 调用common,也就是android_native_base_t的incRef和decRef函数,具体函数是什么还不知道
  13. void incStrong(const void* /*id*/) const {
  14. common.incRef(const_cast<android_native_base_t*>(&common));
  15. }
  16. void decStrong(const void* /*id*/) const {
  17. common.decRef(const_cast<android_native_base_t*>(&common));
  18. }
  19. #endif
  20. // common的incRef和decRef还没有明确是什么
  21. struct android_native_base_t common;
  22. int width;
  23. int height;
  24. int stride;
  25. int format;
  26. int usage;
  27. void* reserved[2];
  28. // buffer_handle_t是指向sturct native_handle, native_handle_t, struct private_handle_t的指针.
  29. buffer_handle_t handle;
  30. void* reserved_proc[8];
  31. } ANativeWindowBuffer_t;
  32. // Old typedef for backwards compatibility.
  33. typedef ANativeWindowBuffer_t android_native_buffer_t;

ANativeWindow的定义如下

  1. struct ANativeWindow
  2. {
  3. #ifdef __cplusplus
  4. ANativeWindow()
  5. : flags(0), minSwapInterval(0), maxSwapInterval(0), xdpi(0), ydpi(0)
  6. {
  7. // ANDROID_NATIVE_WINDOW_MAGIC的值是"_wnd"
  8. common.magic = ANDROID_NATIVE_WINDOW_MAGIC;
  9. common.version = sizeof(ANativeWindow);
  10. memset(common.reserved, 0, sizeof(common.reserved));
  11. }
  12. /* Implement the methods that sp<ANativeWindow> expects so that it
  13. can be used to automatically refcount ANativeWindow's. */
  14. // 调用common,也就是android_native_base_t的incRef和decRef函数,具体函数是什么还不知道
  15. void incStrong(const void* /*id*/) const {
  16. common.incRef(const_cast<android_native_base_t*>(&common));
  17. }
  18. void decStrong(const void* /*id*/) const {
  19. common.decRef(const_cast<android_native_base_t*>(&common));
  20. }
  21. #endif
  22. // common的incRef和decRef还没有明确是什么
  23. struct android_native_base_t common;
  24. ...
  25. int     (*dequeueBuffer)(struct ANativeWindow* window,
  26. struct ANativeWindowBuffer** buffer, int* fenceFd);
  27. int     (*queueBuffer)(struct ANativeWindow* window,
  28. struct ANativeWindowBuffer* buffer, int fenceFd);
  29. int     (*cancelBuffer)(struct ANativeWindow* window,
  30. struct ANativeWindowBuffer* buffer, int fenceFd);
  31. };
  32. /* Backwards compatibility: use ANativeWindow (struct ANativeWindow in C).
  33. * android_native_window_t is deprecated.
  34. */
  35. typedef struct ANativeWindow ANativeWindow;
  36. typedef struct ANativeWindow android_native_window_t __deprecated;

我们目前需要注意的是ANativeWindow的函数指针成员所指向的函数都需要一个struct ANativeWindowBuffer* buffer的参数.

ANativeWindowBuffer和ANativeWindow还是没有给android_native_base_t的incRef和decRef指针赋值,ANativeWindowBuffer和ANativeWindow两个还是可以理解为抽象类!

5. GraphicBuffer和Surface

frameworks/native/include/ui/GraphicBuffer.h

  1. class GraphicBuffer
  2. : public ANativeObjectBase< ANativeWindowBuffer, GraphicBuffer, RefBase >,
  3. public Flattenable<GraphicBuffer>
  4. {
  5. ...
  6. }

GraphicBuffer继承于模版类ANativeObjectBase,这个模版类有三个模版.

frameworks/native/include/ui/ANativeObjectBase.h

  1. // NATIVE_TYPE=ANativeWindowBuffer TYPE=GraphicBuffer REF=RefBase
  2. template <typename NATIVE_TYPE, typename TYPE, typename REF>
  3. // ANativeObjectBase多重继承于ANativeWindowBuffer和RefBase
  4. class ANativeObjectBase : public NATIVE_TYPE, public REF
  5. {
  6. public:
  7. // Disambiguate between the incStrong in REF and NATIVE_TYPE
  8. // incStrong和decStrong直接调用其中一个基类RefBase的对应函数
  9. void incStrong(const void* id) const {
  10. REF::incStrong(id);
  11. }
  12. void decStrong(const void* id) const {
  13. REF::decStrong(id);
  14. }
  15. protected:
  16. // 给ANativeObjectBase取了个别名BASE
  17. typedef ANativeObjectBase<NATIVE_TYPE, TYPE, REF> BASE;
  18. ANativeObjectBase() : NATIVE_TYPE(), REF() {
  19. // 构造函数中给ANativeWindowBuffer.common的两个函数指针赋值了!这两个指针就是我们之前在分析ANativeWindowBuffer的时候悬而未决的地方.
  20. // incRef和decRef指针分别指向内部函数incRef和decRef
  21. NATIVE_TYPE::common.incRef = incRef;
  22. NATIVE_TYPE::common.decRef = decRef;
  23. }
  24. static inline TYPE* getSelf(NATIVE_TYPE* self) {
  25. return static_cast<TYPE*>(self);
  26. }
  27. static inline TYPE const* getSelf(NATIVE_TYPE const* self) {
  28. return static_cast<TYPE const *>(self);
  29. }
  30. static inline TYPE* getSelf(android_native_base_t* base) {
  31. return getSelf(reinterpret_cast<NATIVE_TYPE*>(base));
  32. }
  33. static inline TYPE const * getSelf(android_native_base_t const* base) {
  34. return getSelf(reinterpret_cast<NATIVE_TYPE const*>(base));
  35. }
  36. // 内部函数incRef和decRef调用上面的incStong和decStrong,也就是说ANativeWindowBuffer.common的两个函数指针最终会调用到RefBase的incStrong和decStrong.
  37. static void incRef(android_native_base_t* base) {
  38. ANativeObjectBase* self = getSelf(base);
  39. self->incStrong(self);
  40. }
  41. static void decRef(android_native_base_t* base) {
  42. ANativeObjectBase* self = getSelf(base);
  43. self->decStrong(self);
  44. }
  45. };

搞了半天,原来GraphicBuffer就是ANativeWindowBuffer一种具体实现,把ANativeWindowBuffer的common成员的两个函数指针incRef

decRef指向了GraphicBuffer的另一个基类RefBase的incStrong和decStrong,而ANativeWindowBuffer无非就是把buffer_handle_t包了一层.我们看下另外一个从ANativeObjectBase派生的类,他就是大名鼎鼎的,Surface!

frameworks/native/include/gui/Surface.h

  1. class Surface
  2. : public ANativeObjectBase<ANativeWindow, Surface, RefBase>
  3. {
  4. enum { NUM_BUFFER_SLOTS = BufferQueue::NUM_BUFFER_SLOTS };
  5. ...
  6. struct BufferSlot {
  7. sp<GraphicBuffer> buffer;
  8. Region dirtyRegion;
  9. };
  10. // mSlots stores the buffers that have been allocated for each buffer slot.
  11. // It is initialized to null pointers, and gets filled in with the result of
  12. // IGraphicBufferProducer::requestBuffer when the client dequeues a buffer from a
  13. // slot that has not yet been used. The buffer allocated to a slot will also
  14. // be replaced if the requested buffer usage or geometry differs from that
  15. // of the buffer allocated to a slot.
  16. BufferSlot mSlots[NUM_BUFFER_SLOTS];
  17. ...
  18. }

Surface和GraphicBuffer都继承自模版类ANativeObjectBase,他使用的三个模版是ANativeWindow,
Surface, RefBase,关于incRef和decRef两个函数指针的指向问题和上面GraphicBuffer是完全相同的,
这里就不赘述了.我们需要注意的是Surface有一个BufferSlot类型的成员数组mSlots,BufferSlot是GraphicBuffer的包装,所以我们可以理解为每个Surface中都有一个大小为NUM_BUFFER_SLOTS的GraphicBuffer数组.

因为Surface继承自ANativeWindow,所以Surface需要实现ANativeWindow中定义的一些接口,这些实现在Surface的构造函数中:

frameworks/native/libs/gui/Surface.cpp

  1. Surface::Surface(
  2. const sp<IGraphicBufferProducer>& bufferProducer,
  3. bool controlledByApp)
  4. : mGraphicBufferProducer(bufferProducer)
  5. {
  6. // Initialize the ANativeWindow function pointers.
  7. ANativeWindow::setSwapInterval  = hook_setSwapInterval;
  8. ANativeWindow::dequeueBuffer    = hook_dequeueBuffer;
  9. ANativeWindow::cancelBuffer     = hook_cancelBuffer;
  10. ANativeWindow::queueBuffer      = hook_queueBuffer;
  11. ANativeWindow::query            = hook_query;
  12. ANativeWindow::perform          = hook_perform;
  13. ANativeWindow::dequeueBuffer_DEPRECATED = hook_dequeueBuffer_DEPRECATED;
  14. ANativeWindow::cancelBuffer_DEPRECATED  = hook_cancelBuffer_DEPRECATED;
  15. ANativeWindow::lockBuffer_DEPRECATED    = hook_lockBuffer_DEPRECATED;
  16. ANativeWindow::queueBuffer_DEPRECATED   = hook_queueBuffer_DEPRECATED;
  17. const_cast<int&>(ANativeWindow::minSwapInterval) = 0;
  18. const_cast<int&>(ANativeWindow::maxSwapInterval) = 1;
  19. }

ANativeWindow定义的这些接口有什么用呢?谁会来call这些函数呢?举个例子来看.我们在EGL的api中可以找到eglCreateWindowSurface这个函数的定义:

frameworks/native/opengl/libs/EGL/eglApi.cpp

  1. EGLSurface eglCreateWindowSurface(  EGLDisplay dpy, EGLConfig config,
  2. NativeWindowType window,
  3. const EGLint *attrib_list)
  4. {
  5. ...
  6. }

注意其中一个参数NativeWindowType window,这个NativeWindowType又是什么呢?

frameworks/native/opengl/include/EGL/eglplatform.h

  1. typedef struct ANativeWindow*           EGLNativeWindowType;
  2. typedef EGLNativeWindowType  NativeWindowType;

原来NativeWindowType在Android环境下,就是ANativeWindow*,也就是Surface*!

总结一下,

native_handle/native_handle_t是private_handle_t的抽象表示方法,消除平台相关性,方便private_handle_t所表示的memory信息在android各个层次之间传递.而buffer_handle_t是指向他们的指针.

ANativeWindowBuffer将buffer_handle_t进行了包装,ANativeWindow和ANativeWindowBuffer都继承于android_native_base_t,定义了common.incRef和common.decRef两个函数指针,但是并没有为函数指针赋值,所以ANativeWindow和ANativeWindowBuffer仍然是抽象类.

GraphicBuffer和Surface通过继承模版类ANativeObjectBase并指定其中一个模版是RefBase,为incRef和decRef两个指针分别赋值为RefBase的incStrong和decStrong,这样

GraphicBuffer继承了ANativeWindowBuffer,Surface继承了ANativeWindow,并且两者都具有的和RefBase同样的incStong decStrong成员函数.

Surface的成员BufferSlot
mSlots[NUM_BUFFER_SLOTS];可以看作是sp<GraphicBuffer>类型的数组,也就是说每个Surface中都包含有NUM_BUFFER_SLOTS个sp<GraphicBuffer>.

关于ANativeWindow的使用方法,我们可以在SurfaceFlinger中找到一个很好的列子,就是SF的captureScreen接口.

Android中*_handle_t/ANativeWindowBuffer/ANativeWindow/GraphicBuffer/Surface的关系的更多相关文章

  1. Android中图片大小和屏幕密度的关系讲解

    Android手机适配是非常让人头疼的一件事,尤其是图片,android为了做到是适配提供了很多文件夹来存放不同大小的图片,比如:drawable-ldpi.drawable-mdpi.drawabl ...

  2. Android 中Activity,Window和View之间的关系

    转自:http://hi.baidu.com/xiaofanqing/blog/item/8261ac114ab14f64cb80c435.html 我这里根据我个人的理解来讲讲我个人对这3个概念的理 ...

  3. Android中dp、dpi与px的关系

    转自知乎用户的回答: 1. dpi是dot per inch,每英寸多少点,ppi是 Pixel per inch,每英寸像素数,针对显示器的设计时,dpi=ppi.ppi计算方法是长宽各自平方之和开 ...

  4. android中的EditView控件

    android中的EditView控件 EditText继承关系:View-->TextView-->EditText ,EditText是可编辑文本框 1.EditText默认情况下,光 ...

  5. Android中的GraphicBuffer同步机制-Fence

    Fence是一种同步机制,在Android里主要用于图形系统中GraphicBuffer的同步.那它和已有同步机制相比有什么特点呢?它主要被用来处理跨硬件的情况.尤其是CPU.GPU和HWC之间的同步 ...

  6. Android中的Surface和SurfaceView

    一.什么是Surface 简单的说Surface对应了一块屏幕缓冲区,每个window对应一个Surface,任何View都要画在Surface的Canvas上(后面有原因解释).传统的view共享一 ...

  7. Android中的Surface, SurfaceHolder, SurfaceHolder.Callback, SurfaceView

    传入一个surface,然后让openGL在surface上画图 window->view hierachy(DecorView是tree的root)->ViewRoot->Surf ...

  8. Android中直播视频技术探究之---桌面屏幕视频数据源采集功能分析

    一.前言 之前介绍了Android直播视频中一种视频源数据采集:摄像头Camera视频数据采集分析 中介绍了利用Camera的回调机制,获取摄像头的每一帧数据,然后进行二次处理进行推流.现在我们在介绍 ...

  9. Android中直播视频技术探究之---基础知识大纲介绍

    一.前言 最近各种视频直播app到处都是,各种霸屏,当然我们也是需要体验的,关于视频直播的软件这里就不介绍了,在不是技术的人来看,直播是一种潮流,是一种娱乐方式,但是作为一个高技术的,我们除了看看,更 ...

随机推荐

  1. JavaScript跳转到页面某个锚点#

    JavaScript跳转到页面某个锚点: scroll(0, document.getElementById('锚点ID').offsetTop);

  2. SpringBoot定时任务(Spring Schedule )实现方法

    FastDateFormat fdf = FastDateFormat.getInstance("yyyy-MM-dd HH:mm:ss"); fdf.format(new Dat ...

  3. 一良心操盘手:我们是这样玩死散户的! z

    做庄必须考虑很多问题: 第一是证监会的监控.操控股票不能让他们抓住把柄,这时候就要考虑多户头,或者拉几个私募大户集体作战. 第二要考虑产业资本的问题.如果我们拉的时候,他们看到利润可观,结果大量抛出筹 ...

  4. 【Sofa】Sofa比赛成绩记录

    最高得到过第4名,然后后面跌倒了第7名,现在追到了第6名.虽然名次还不是最高,但是很开心,今天能在一道一直困扰的题目上有突破,就是那个自行车预测的题目,开始过拟合了.后面进行了一些处理,效果很明显.继 ...

  5. Java程序员到架构师的推荐阅读书籍

    作为Java程序员来说,最痛苦的事情莫过于可以选择的范围太广,可以读的书太多,往往容易无所适从.我想就我自己读过的技术书籍中挑选出来一些,按照学习的先后顺序,推荐给大家,特别是那些想不断提高自己技术水 ...

  6. 通过idea 打包 spring maven项目打包为可执行jar包

    用assembly打包一直报错: shangyanshuodeMacBook-Pro:target shangyanshuo$ java -jar jobscrawler-1.0-SNAPSHOT-j ...

  7. RabbitMQ搭建

    1. RabbitMQ简介 RabbitMQ是一个在AMQP基础上完整的,可复用的企业消息系统.他遵循Mozilla Public License开源协议 2.安装与部署 RabbitMQ的安装依赖E ...

  8. MapReduce源代码分析之JobSubmitter(一)

    JobSubmitter.顾名思义,它是MapReduce中作业提交者,而实际上JobSubmitter除了构造方法外.对外提供的唯一一个非private成员变量或方法就是submitJobInter ...

  9. 初学spring(一)

    1.spring 在ssh 中所处的位置 struts 是web框架(jsp,action,actionform) hibernate 是orm框架,处于数据持久层 spring 是容器框架,配置be ...

  10. Html Table用JS导出excel格式问题 导出EXCEL后单元格里的000412341234会变成412341234 7-14 会变成 2018-7-14(7月14) 自定义格式 web利用table表格生成excel格式问题 js导出excel增加表头、mso-number-format定义数据格式 数字输出格式转换 mso-number-format:"\@"

    Html Table用JS导出excel格式问题 我在网上找的JS把HTML Tabel导出成EXCEL.但是如果Table里的数字内容为0开的的导成Excel后会自动删除0,我想以text的格式写入 ...