Android应用程序与SurfaceFlinger服务是运行在不同的进程中的,因此,它们采用Binder进程间通信机制来进行通信。

但是我们知道一个Android应用程序可能会有很多个窗口,而每一个窗口都有自己的UI元数据,因此,Android应用程序需要传递给SurfaceFlinger服务的UI元数据是相当可观的。在这种情况下,通过Binder来在Android应用程序与SurfaceFlinger服务之间传递UI元数据是不合适的,因此这里选择了Android系统的匿名共享内存的方案。在每一个Android应用程序与SurfaceFlinger服务之间的连接上加上一块用来传递UI元数据的匿名共享内存。而这块区域被包装为SharedClient。

Android图形系统(八)-app与SurfaceFlinger共享UI元数据过程_第1张图片

在每一个SharedClient里面,有至多31个SharedBufferStack,那什么又是SharedBufferStack?

SharedBufferStack就是共享缓冲区堆栈,每一个SharedBufferStack与一个Surface一一对应,每一个Surface又对应一个窗口,那就是一个应用程序内部最多可创建31个窗口。SharedBufferStack 内部包含N个缓冲buffer, 开篇介绍的双缓冲(front buffer , back buffer) ,三缓冲(front buffer , back buffer, tripple buffer),有了它SurfaceFlinger服务就可以使用N个缓冲区技术来绘制UI了。

Android图形系统(八)-app与SurfaceFlinger共享UI元数据过程_第2张图片

下面我们再来了解下SharedBufferStack的结构:

Android图形系统(八)-app与SurfaceFlinger共享UI元数据过程_第3张图片

SharedBufferStack中分为空闲buffer和已使用的buffer。其中SharedBufferStack中的每一个已经使用了的缓冲区都对应有一个GraphicBuffer,用来描述真正的UI数据。

客户端一次申请GraphicBuffer且将UI元数据写入GraphicBuffer的流程:

当Android应用程序需要更新一个Surface的时候,它就会找到与它所对应的SharedBufferStack,并且从它的空闲缓冲区列表的尾部取出一个空闲的Buffer。我们假设这个取出来的空闲Buffer的编号为index。接下来Android应用程序就请求SurfaceFlinger服务为这个编号为index的Buffer分配一个图形缓冲区GraphicBuffer。SurfaceFlinger服务分配好图形缓冲区GraphicBuffer之后,会将它的编号设置为index,然后再将这个图形缓冲区GraphicBuffer返回给Android应用程序访问。Android应用程序得到了SurfaceFlinger服务返回的图形缓冲区GraphicBuffer之后,就在里面写入UI数据。写完之后,就将与它所对应的缓冲区,即编号为index的Buffer,插入到对应的SharedBufferStack的已经使用了的缓冲区列表的头部去。这一步完成了之后,Android应用程序就通知SurfaceFlinger服务去绘制那些保存在已经使用了的缓冲区所描述的图形缓冲区GraphicBuffer了。

那么我们也知道一个绘图表面,在SurfaceFlinger服务和Android应用程序中分别对应Layer对象和Surface对象,其中这两个对象在内部分别使用一个SharedBufferServer对象和一个SharedBufferClient对象来操作这个绘图表面的UI元数据缓冲堆栈。操作过程如下:

在Android应用程序这一侧,当它需要渲染一个Surface时,它就会首先找到对应的SharedBufferClient对象,然后再调用它的成员函数dequeue来请求分配一个UI元数据缓冲区。有了这个UI元数据缓冲区之后,Android应用程序再调用这个SharedBufferClient对象的成员函数setDirtyRegion、setCrop和setTransform来设置对应的Surface的裁剪区域、纹理坐标以及旋转方向。此外,Android应用程序还会请求SurfaceFlinger服务为这个Surface分配一个图形缓冲区,以便可以往这个图形缓冲区写入实际的UI数据。最后,Android应用程序就可以调用这个SharedBufferClient对象的成员函数queue把前面已经准备好了的UI元数据缓冲区加入到它所描述的一个UI元数据缓冲区堆栈的待渲染队列中,以便SurfaceFlinger服务可以在合适的时候对它进行渲染。当SurfaceFlinger服务需要渲染一个Surface的时候,它就会找到对应的一个SharedBufferServer对象,然后调用它的成员函数getQueueCount来检查它所描述的一个UI元数据缓冲区堆栈的待渲染队列的大小。如果这个大小大于0,那么SurfaceFlinger服务就会继续调用它的成员函数retireAndLock来取出队列中的第一个UI元数据缓冲区,以及调用它的成员函数getDirtyRegion、getCrop和getTransform来获得要渲染的Surface的裁剪区域、纹理坐标和旋转方向。最后,SurfaceFlinger服务就可以结合这些信息来将保存这个Surface的图形缓冲区中的UI数据渲染在显示屏中。

Android图形系统(八)-app与SurfaceFlinger共享UI元数据过程_第4张图片

另外想深入了解BufferQueue的生产者消费者模型,详细可以阅读下如下这篇博文,感觉还不错:https://blog.csdn.net/stn_lcd/article/details/73801313

Android图形系统(八)-app与SurfaceFlinger共享UI元数据过程_第5张图片

参考:
https://blog.csdn.net/Luoshengyang/article/details/7867340

更多相关文章

  1. android 开发-数据存储之文件存储
  2. Android应用程序的签名
  3. 打造android ORM框架opendroid(四)——优雅的删除数据
  4. Android之ORMLite实现数据持久化的简单使用
  5. android访问远程数据库
  6. Android系统Surface机制的SurfaceFlinger服务渲染应用程序UI的过

随机推荐

  1. 如何实现android清理后台时,自己的软件不
  2. Android App Ant打包
  3. Android 软键盘弹出隐藏挤压界面等各种问
  4. Android触摸屏开发知识汇总
  5. android 模拟器创建的sdcard 没有mount
  6. android 手机存储介质大全
  7. Android:TextView属性大全
  8. Mars Android视频学习笔记——01_16_SQLi
  9. Smalidea+IntelliJ IDEA/Android Studio
  10. Android高效编程注意事项