一、Android系统显示原理
Android的显示过程可以简单概括为:Android应用程序把经过测量、布局、绘制后的surface缓存数据、通过SurfaceFlinger把数据渲染到显示屏幕上,通过Android的刷新机制来刷新数据。也就是说应用层负责绘制,系统层负责渲染,通过进程间通信把应用层需要绘制的数据传递到系统层服务,系统层服务通过刷新机制把数据更新到屏幕。
1、绘制原理
应用层
在Android的每个View都会经过Measure和Layout来确定当前需要绘制的View所在的大小和位置,然后,再通过Draw绘制到surface上。在Android系统中整体的绘制源码是在ViewRootImpl类的performTraversals()方法,通过这个方法可以看出Measure和Layout都是递归来获取View的大小和位置,并且以深度作为优先级。显然,层级越深,元素越多,耗时就越长。
对于绘制,Android支持两种绘制方式:
- 软件绘制(CPU)
- 硬件绘制(GPU)
硬件加速从Android 3.0开始支持,它在UI显示和绘制效率方面远高于软件绘制。但它的局限如下:
- 耗电:GPU功耗高于CPU。
- 兼容性:不兼容某些接口和函数。
- 内存大:使用OpenGL的接口需要占用内存8MB。
系统层
将数据渲染到屏幕上是通过系统级进程中的SurfaceFlinger服务来实现的,它的主要工作流程如下:
- 1、响应客户端事件,创建Layer与客户端的Surface建立连接。
- 2、接收客户端数据和属性,修改Layer属性,如尺寸、颜色、透明度等。
- 3、将创建的Layer内容刷新到屏幕上。
- 4、维持Layer的序列,并对Layer的最终输出做裁剪计算。
其中,SurfaceFlinger系统进程和应用进程使用了匿名共享内存SharedClient,并且,每一个应用和SurfaceFlinger之间都会创建一个SharedClient,在每个SharedClient中,最多可以创建31个SharedBufferStack,每一个SharedBufferStack对应一个Surface,即一个window。(其中包含了两个(小于4.1版本)或者三个(4.1及以上版本)缓冲区)
因此,从上可知,一个Android应用程序最多可以包含31个窗口。最后,显示的整体流程如下:
- 1、应用层绘制到缓冲区。
- 2、SurfaceFlinger把缓冲区数据渲染到屏幕,其中使用了Android匿名共享内存SharedClient缓存需要显示的数据来达到目的。
绘制的过程首先是 CPU准备数据,通过Driver层把数据交给CPU渲染,其中CPU主要负责Measure、Layout、Record、Execute的数据计算工作,GPU负责Rasterization(栅格化)、渲染。因为图形API不允许CPU直接和GPU通信,所以要通过一个图形驱动的中间层来进行连接,在图形驱动里面维护了一个队列,CPU把display list(待显示的数据列表)添加到队列中,GPU从这个队列中取出数据进行绘制,最终才在显示屏上显示出来。
Android系统每隔16ms发出VSYNC信号,触发对UI进行渲染,如果每次渲染都成功,这样就能够达到流畅画面所需的60FPS。
2、刷新机制
在4.1版本的Project Butter中对Android Display系统进行了重构,引入了三个核心元素:VSYNC(Vertical Synchronization)、Triple Buffer(三级缓冲)、Choreographer。其中作为Project Buffer核心的VSYNC,即垂直同步可认为是一种定时中断。而Choreographer起调度的作用,将绘制工作统一到VSYNC的某个时间点上,使应用的绘制工作有序。
那么,为什么要推出Project Butter呢?
目的是解决刷新不同步的问题。
在Tripe Buffer出现之前,Android的显示系统采用的是双缓冲技术。
为什么要使用双缓冲技术?
在Linux上通常使用 Framebuffer 来做显示输出,当用户进程更新Framebuffer中的数据后,显示驱动会把FrameBuffer中每个像素点的值更新到屏幕,但是如果上一帧数据还没显示完,Framebuffer中的数据又更新了,就会带来残影的问题,用户会觉得有闪烁感,所以采用了双缓冲技术。
双缓冲的含义?
双缓冲意味着要使用两个缓冲区(在上文提及的SharedBufferStack中),其中一个称为Front Buffer