Android中的图形系统采用Client/Server架构。Server (即SurfaceFlinger)主要由c++代码编写而成。
Client端代码分为两部分,一部分是由Java提供的供应用使用的api,另一部分则是由c++写成的底层实现。
下图概要介绍了android图形系统的架构以及使用到的主要组件。
Android图形系统中一个重要的概念和线索是surface。View及其子类(如TextView, Button)要画在surface上。
每个surface创建一个Canvas对象(但属性时常改变),用来管理view在surface上的绘图操作,如画点画线。每个canvas对象对应一个bitmap,存储画在surface上的内容。
每个Surface通常对应两个buffer,一个front buffer, 一个back buffer。其中,back buffer就是canvas绘图时对应的bitmap
(研究android_view_Surface.cpp::lockCanvas)。因此,绘画总是在back buffer上,需要更新时,则将back buffer和front buffer互换。

Layer的概念:

每个surface又对应一个layer, SurfaceFlinger负责将各个layer的front buffer合成(composite)绘制到屏幕上。

1Surfaceflinger线程
Surfaceflinger是一个类,同时又是线程,该线程通过循环,不断计算并刷新当前屏幕需要的显示内容。
Surfaceflinger线程属于SystemServer进程,也就是在SystemServer进程中启动了Surfaceflinger线程。
Surfaceflinger中保存着各种layer,其主要工作就是负责各种layer的融合,因此可看做一个用于维护各种layer的线程。
启动Android线程需要提供两个接口,
一是readyToRun(),该函数定义了线程循环前需要初始化的内容;
二是threadLoop(),每个线程都必须实现,该函数定义了线程执行的内容,如果该函数返回true,线程会继续调用threadLoop(),如果返回false,线程将退出。

2初始化
Surfaceflinger类的构造函数会执行init(),该函数输出Surfaceflinger启动信息,并配置一些调试信息。接着执行readyToRun(),初始化整个显示系统。
readyToRun()调用过程如下:
(1)执行newDisplayHardware(this,dpy),通过DisplayHardware初始化Framebuffer、EGL并获取OpenGLES信息。
(2)创建共享的内存控制块。
(3)将EGL与当前屏幕绑定。
(4)初始化共享内存控制块。
(5)初始化OpenGLES。
(6)显示开机动画。


const GraphicPlane& SurfaceFlinger::graphicPlane(int dpy) const
{
LOGE_IF(uint32_t(dpy) >= DISPLAY_COUNT, "Invalid DisplayID %d", dpy);
const GraphicPlane& plane(mGraphicPlanes[dpy]);//android 考虑了多个屏幕的情况。为此引入GraphicPlane对象,SurfaceFlinger包含GraphicPlane数组,
在每个GraphicPlane中,包含一个DisplayHardware显示缓冲区,
return plane;
}

if(videoHoleChanged()){
const DisplayHardware& hw(graphicPlane(0).displayHardware());
mDirtyRegion.set(hw.bounds());
signalEvent(); //videohole改变了,发信号,消息队列刷新。

void SurfaceFlinger::signalEvent() {
mEventQueue.invalidate();
}
ReadytoRun中,首先建立GraphicPlane ,再建立FrameBufferHardware(确定输出目标)
初始化openGL ,建立主surface,所以layer都要先画到这个主surface上。
3核心数据结构
State mCurrentState;
当前更新的状态
State mDrawingState;
正在屏幕上绘制的状态
LayerVector layersSortedByZ;
保存layer的列表,类似于Z轴,mCurrentState和mDrawingState分别拥有一个列表。

4主循环threadLoop()
通过流程图可以看到threadLoop()都做了哪些操作。
4.1waitForEvent函数
waitForEvent函数将超时时间设置为5秒钟,并等待系统事件发生。在超时前若有事件发生则立即返回,若发生超时将输出警告信息,上层一般会处理这个问题。
4.2handleConsoleEvents函数
该函数被执行的几率较低,主要用于处理控制台事件。
4.3handleTransaction函数
该函数将遍历Surfaceflinger拥有的每一个layer,检查是否有layer的属性改变,主要执行以下工作:
(1)获取mCurrentState.layersSortedByZ及layer的数目。
(2)遍历所有layer,获取layer对应的参数,判断是否有layer的属性改变和是否有需要显示的layer。
(3)更新主屏幕参数:
如果屏幕需要旋转,则需更新所有可见区域和共享控制块,并计算旋转参数;
判断主屏幕是否需要被冻结;
判断是否有新加入的layer;
去除不再需要的layer,通过ditchedLayers.add(layer)释放资源;
(4)通过广播更新所有改变。
4.4handlePageFlip函数
该函数主统计所有layer的信息,针对需要的layer进行重绘,并计算屏幕实际可显示区域。
(1)调用lockPageFlip(currentLayers)
遍历currentLayers包含的所有layer,依次调用每层layer对应的lockPageFlip函数。首先通过retireAndLock函数取得新的frontbuffer,然后获取并计算脏的区域,最后调用reloadTexture函数更新这些区域。
(2)如果有需要显示的layer,调用computeVisibleRegions函数计算经过混合后每个layer的显示区域。每一个layer拥有三片区域,分别为opaqueRegion、visibleRegion和coveredRegion,主屏幕则拥有aboveOpaqueLayers、aboveCoveredLayers。在遍历每一层layer时,要计算没个layer对应的区域,同时同步更新主屏幕的aboveOpaqueLayers和aboveCoveredLayers。
(3)调用unlockPageFlip(currentLayers)
遍历currentLayers包含的所有layer,依次调用每层layer对应的unlockPageFlip函数,完成layer到屏幕的坐标变换。
4.5handleRepaint函数
handlePageFlip更新并计算每一个独立layer的显示区域,handleRepaint则负责将每一个layer经过计算的显示区域数据搬运至屏幕的显存中。
(1)根据不同的屏幕类型,设定更新模式,有部分更新、缓存更新、矩形框交换和全屏更新。
(2)调用composeSurfaces(mDirtyRegion)
该函数将遍历每一层layer,调用layer对应的onDraw接口,将数据从layer的缓存搬运至屏幕的显存中。
4.6hw.compositionComplete函数
该函数会调用到gralloc模块的fb_compositionComplete接口,是提供给屏幕的回调接口,目前并没有实现任何功能,根据采用屏幕的不同可能需要填充相应操作。
4.7unlockClients函数
unlockClients函数将遍历每一层layer,调用finishPageFlip释放layer用于的共享控制块。
4.8postFramebuffer函数
handleRepaint函数执行的搬运操作实际将显示数据搬运至屏幕的后缓冲中,postFramebuffer最终将调用到eglSwapBuffers(dpy,surface),交换屏幕的后缓冲和前缓冲,实现显示更新。
4.9另一条路线
如果hw.canDraw返回错误或者屏幕此时被冻结,那么将无法进行数据更新,此时将都另外一条路线,直接调用unlockClients,并休眠16667微秒。如果显示出现问题,16667微秒将保证每秒最多执行60次threadLoop函数
)、composeSurfaces

该接口在Threadloop中被调用,负责将所有存在的surface进行合并,OpenGl模块负责这个部分。
3)、createSurface

提供给应用程序的主要接口,该接口可以创建一个surface,底层会根据参数创建layer以及分配内存,surface相关参数会反馈给上层


6)、postFramebuffer

该接口在Threadloop中被调用,负责将合成好的数据(存于back buffer中)推入在front buffer中,然后调用HAL接口命令底层显示。

7)、从3中可知,上层每创建一个surface的时候,底层都会同时创建一个layer,下面看一下surface及layer的相关属性。

Note:code中相关结构体太大,就不全部罗列出来了

A、Surface相关属性(详细参考文件surface.h)

a1:SurfaceID:根据此ID把相关surface和layer对应起来

a2:SurfaceInfo
包括宽高格式等信息

a3:2个buffer指针、buffer索引等信息

B、Layer相关属性(详细参考文件layer.h/layerbase.h/layerbitmap.h)

包括Layer的ID、宽高、位置、layer、alpha指、前后buffer地址及索引、layer的状态信息(如eFlipRequested、eBusy、eLocked等)

更多相关文章

  1. C语言函数的递归(上)
  2. Android(安卓)Studio 中利用 Android(安卓)Profiler 测量应用性
  3. 阿里ctf-2014 android 第一、二题
  4. Android(安卓)浅谈AsyncTask异步
  5. handler机制简析
  6. BroadcastReceiver 该思考的问题(沉思篇)
  7. 【Service 1】Android(安卓)Remote Service - AIDL
  8. 《深入理解Android(安卓)卷1》读书笔记 (二)—— Android(安卓)zyg
  9. Android(安卓)电源管理 (部分转载)

随机推荐

  1. Android与服务器端数据交互(基于SOAP协议
  2. android如何用代码实现界面ui
  3. android studio 签名配置
  4. Android页面跳转是如何传递参数的
  5. 分享一个Android左右侧滑的效果实现 slid
  6. android 操作路由表
  7. Android 之 LayoutInflater
  8. Android ANR 分析
  9. Android中可自由移动悬浮窗口的Demo
  10. Android(安卓)机型适配之百分比适配 Cons