[TOC]
Android图形显示子系统概述
Android图形显示系统,是Android比较重要的一个子系统,和很多其他子系统的关联紧密。想象一下,没有图形显示系统的手机是什么样子,可能连对讲机都不如吧。图形显示系统比较复杂,从Android诞生到现在,几经修改,已经变的越来越庞大了。总的说来,图形显示系统可以分为两大部分来理解:
- 图形系统
- 显示系统
图形系统
图形系统也就是图形支持系统,提供绘图和图形处理支持。包括最初的2D绘图API Skia,后来的3D绘图API OpenGLES,RenderScript,OpenCV,到最近的Vulkan。也包括图片解码库,jpg,png,gif等。以及它们所需要的各种Driver支持。
但是Android为了方便大家,我们在做应用开发的时候,并不用大家直接用各种API去绘制界面,也不用直接用解码库去解码。Android已经给大家提供了一个界面绘制机制,有很多widget和view,Android的应用开发者,用现有的widget就能够绘制出比较酷炫的界面。
Android提供的大多view和widget都是2D的绘图,2D绘图比较慢,也发挥不出GPU的作用,因此Android又设计了一套加速系统,硬件加速。其目的就是将2D的绘图操作转换为一个个的3D(Opengl)绘图,再采用部分更新的方式,只去重绘界面中有更新的部分view,这样就大大提升界面绘制的速度。
显示系统
图形绘制好了后,需要送到LCD显示屏上,我们才能看到。绘制界面时,我们只关心单个界面,显示的时候,可能就有多个界面了。做过Android应该开发的都知道,我们需要继承一个Activity,用Activity呈现我们的界面。Activity的生命周期管理,也就伴随了窗口的管理。这中间就涉及了两个Android中两个主要的服务,AMS(ActivityManagerService)和WMS(WindowManagerService)。View,AMS,WMS可以说是整个上层显示系统的三驾马车。
在Android中,一个窗口用一个Surface描述。多个窗口(窗口不一定都是Activity),需要同时显示,我们就需要将多个窗口进行合并。这就需要显示系统中重量级的服务SurfaceFlinger,Surfaceflinger控制窗口的合成,将多个窗口合并成一个,再送到LCD。
Surfaceflinger是Native的服务,Surfaceflinger中怎么去描述一个窗口呢?Surfaceflinger采用图层的概念,即Layer。SurfaceFlinger合成,就是基于Display HAL的实现,将多个Layer合并。Display HAL,各个厂商的实现就千差万别了。
Buffer管理
前面讨论了怎么绘制,怎么显示。但是,绘制,绘在什么地方,拿什么去显示。答案只能是内存Buffer。Android的系统中,采用GraphicBuffer对buffer进行封装,而buffer采用ion实现,能在进程间共享。
Surface属性应用进程,Layer属于SurfaceFlinger进程。如果只用一个Buffer,那么两个进程都有可能同时在用Buffer,这就可能会造成我们看到的屏幕显示不对,存在撕裂。另外,只用一个Buffer,效率也不高啊,绘制本来就是GPU在绘制,显示这边是CPU或者是其他的硬件模块,一个工作,另外一个不工作,且不浪费。所以Android采用Buffer队列的方式,即BufferQueue。绘制的是一个Buffer,显示的是一个buffer,各自处理完后,交换一下Buffer。这样效率就高很多了。这中间再采用一个生产者-消费者模型,Buffer是载体,Surface应用这边是Producer,SurfaceFlinger这边是是Consumer。这样就更好理解了。
显示系统的架构
有了前面的描述,是不是对Android的图形显示系统有了大概的认识了?没有关系,我们直接来看架构图。架构图来自Androd的官网, https://source.android.com/devices/graphics/ ,
大家可以对照图再回味一下,前面的描述。有些地方,这个图并不能很好的体现,不过没有关系,接下来我们会详细的介绍各个模块和流程。
换一种方式来描述Android的显示系统,架构图如下:
再和前面Android的图进行对照,是不是更清楚一些了。
这个图里,前面的描述里有点没有说到,SurfaceFlinger到OpenGLES,大家是不是觉得有点奇怪。其实是这样的,SurfaceFlinger合成,有两种方式,Client和Device。Client就是Client合成完Layer后再将合成后的数据给到HWComposer,HWComposer此时做的工作很少,直接给到Display。Device则是将未合成的Layer,给到硬件合成的设备,合成完后再给到Display。
可能大家还是很迷茫,没有关系~,我们接下来将参照Android的源码,逐一为大家讲解。
从应用的角度理解Android
做Android开发,我们都讲了太多的架构,也听了太多的架构。不知道大家有没有从应用的角度去看过Android的系统?我们先来看Android的整体系统架构。
Android基于Linux内核,我们是不是可以将上层Android理解为Linux内核的一个应用。这个应用非常庞大,集集了电话,BT,WiFi,音视频播放,Camera等功能。
基于Linux内核的系统非常的多,比如常用的,Debian系列的Ubuntu,Debian;Redhat系统的RedHat,Fedora等。你可以理解Android自成一个系列。所以,我们也可以基于Linux内核去开发自己的系统。
回到Android,Android在Linux中加了很多驱动,再采用硬件抽象的方式,向上提供接口,这就是我们所说的HAL层。所以我们要增加一个模块,需要增加Linux驱动,然后实现HAL,以供上层使用。当然,我们也可以基于Android的HAL去开发上层的系统,又可以将基于HAL的系统看成一个应用。据了解,FirefoxOS,360OS,YunOS等,基本都是基于Android的HAL的方式去开发的(Oops~如有亵渎,神灵保佑...)。
基于HAL的Android Framework,分为Native Framework和JavaFramework。HAL层是C++写的,按里说,Native的 Framework应该就够了,什么还要去实现Java的Framework呢?Android的应用大多数都是用Java开发,中间还有一个Java虚拟机,和JNI。
其实,这是有历史原因的。现在Android已经形成了一个很大的生态链,但是想想当初,Android系统刚才发布,得有开发者呀,没有开发者的支持,如何能形成生态链。所以,Android就采用了这种Java开发方式,大大笼络了Java开发人员。
再回到我们的显示子系统,Surfaceflinger基于HAL HWComposer,管理和控制着整个Android的显示。而上层,则是WMS,AMS,View等系统服务管理和控制着整个Android的显示。
回到上一章给出的Display架构图,我们是不是可以直接基于Native的Framework进行应用的开发呢,答案是肯定的。Android也为此提供了NDK,以便于Android Native应用的开发。
下面,让我们从一个Native应用开始,揭开Android显示系统的面纱~