zoukankan      html  css  js  c++  java
  • Android系统Surface机制的SurfaceFlinger服务简要介绍和学习计划

    出自:http://blog.csdn.net/luoshengyang/article/details/8010977

     前面我们从Android应用程序与SurfaceFlinger服务的关系出发,从侧面简单学习了SurfaceFlinger服务。有了这些预备知识之后,我们就可以从正面来分析SurfaceFlinger服务的实现原理了。SurfaceFlinger服务负责管理系统的帧缓冲区设备,并且负责渲染系统的UI,即各个应用程序的UI。在本文中,我们就简要介绍SurfaceFlinger服务,并且制定学习计划。

            在前面Android应用程序与SurfaceFlinger服务的关系概述和学习计划一系列的文章中提到,SurfaceFlinger服务运行在System进程中,用来统一管理系统的帧缓冲区设备。由于SurfaceFlinger服务运行在System进程中,因此,Android应用程序就需要通过Binder进程间通信机制来请求它来渲染自己的UI。Android应用程序请求SurfaceFlinger服务渲染自己的UI可以分为三步曲:首先是创建一个到SurfaceFlinger服务的连接,接着再通过这个连接来创建一个Surface,最后请求SurfaceFlinger服务渲染该Surface。

           由于SurfaceFlinger服务需要与Android应用程序执行Binder进程间通信,因此,它本身就是一个Binder本地对象,如图1所示:

    图1 SurfaceFlinger服务的类关系图

            理解这个图需要学习Binder进程间通信机制,具体可以参考Android进程间通信(IPC)机制Binder简要介绍和学习计划这一系列的文章。

            SurfaceFlinger服务实现的接口为ISurfaceComposer,后者定义在文件frameworks/base/include/surfaceflinger/ISurfaceComposer.h中,如下所示:

    1. class ISurfaceComposer : public IInterface  
    2. {  
    3. public:  
    4.     DECLARE_META_INTERFACE(SurfaceComposer);  
    5.     ......  
    6.   
    7.     /* create connection with surface flinger, requires 
    8.      * ACCESS_SURFACE_FLINGER permission 
    9.      */  
    10.     virtual sp<ISurfaceComposerClient> createConnection() = 0;  
    11.   
    12.     /* create a client connection with surface flinger 
    13.      */  
    14.     virtual sp<ISurfaceComposerClient> createClientConnection() = 0;  
    15.   
    16.     /* retrieve the control block */  
    17.     virtual sp<IMemoryHeap> getCblk() const = 0;  
    18.   
    19.     /* open/close transactions. requires ACCESS_SURFACE_FLINGER permission */  
    20.     virtual void openGlobalTransaction() = 0;  
    21.     virtual void closeGlobalTransaction() = 0;  
    22.   
    23.     /* [un]freeze display. requires ACCESS_SURFACE_FLINGER permission */  
    24.     virtual status_t freezeDisplay(DisplayID dpy, uint32_t flags) = 0;  
    25.     virtual status_t unfreezeDisplay(DisplayID dpy, uint32_t flags) = 0;  
    26.   
    27.     /* Set display orientation. requires ACCESS_SURFACE_FLINGER permission */  
    28.     virtual int setOrientation(DisplayID dpy, int orientation, uint32_t flags) = 0;  
    29.   
    30.     /* signal that we're done booting. 
    31.      * Requires ACCESS_SURFACE_FLINGER permission 
    32.      */  
    33.     virtual void bootFinished() = 0;  
    34.   
    35.     /* Capture the specified screen. requires READ_FRAME_BUFFER permission 
    36.      * This function will fail if there is a secure window on screen. 
    37.      */  
    38.     virtual status_t captureScreen(DisplayID dpy,  
    39.             sp<IMemoryHeap>* heap,  
    40.             uint32_t* width, uint32_t* height, PixelFormat* format,  
    41.             uint32_t reqWidth, uint32_t reqHeight) = 0;  
    42.   
    43.     virtual status_t turnElectronBeamOff(int32_t mode) = 0;  
    44.     virtual status_t turnElectronBeamOn(int32_t mode) = 0;  
    45.   
    46.     /* Signal surfaceflinger that there might be some work to do 
    47.      * This is an ASYNCHRONOUS call. 
    48.      */  
    49.     virtual void signal() const = 0;  
    50. };  

            ISurfaceComposer接口有13个成员函数,下面我们就简单介绍一下:

            --createConnection:Android应用程序通过它来请求SurfaceFlinger服务建立一个连接,具体可以参考Android应用程序与SurfaceFlinger服务的连接过程分析一文。

            --createClientConnection:Android应用程序通过它来请求SurfaceFlinger服务创建一块共享UI元数据缓冲区,具体可以参考Android应用程序与SurfaceFlinger服务之间的共享UI元数据(SharedClient)的创建过程分析一文。

            --getCblk:Android应用程序通过它来请求SurfaceFlinger服务返回一块匿名共享内存,返回的匿名共享内存包含了设备显示屏的信息,例如,宽度和高度信息。

            --openGlobalTransaction:Android应用程序通过它请求SurfaceFlinger服务来增加一个全局Transaction计数,用来批量修改UI属性信息。注意,这些被修改的UI属性信息会被缓存起来,不会马上生效。要使得这些被修改的UI属性信息生效,需要调用另外一个成员函数closeGlobalTransaction,如下所述。

            --closeGlobalTransaction:Android应用程序通过它请求SurfaceFlinger服务来减少一个全局Transaction计数。当这个全局Transaction计数减少至0的时候,前面通过openGlobalTransaction来请求修改的UI属性信息就会马上生效。

            --freezeDisplay:Android应用程序通过它来请求SurfaceFlinger服务来冻结屏幕。屏幕在被冻结期间,所有UI渲染操作都会被缓存起来,等待被执行。

            --unfreezeDisplay:Android应用程序通过它来请求SurfaceFlinger服务来解冻屏幕。屏幕被解冻之后,SurfaceFlinger服务就可以执行UI渲染操作了。

            --setOrientation:Android应用程序通过它来请求SurfaceFlinger服务设备屏幕的旋转方向。

            --bootFinished:WindowManagerService通过它来告诉SurfaceFlinger服务,系统启动完成了,这时候SurfaceFlinger服务就会停止执行开机动画,具体可以参考Android系统的开机画面显示过程分析一文。

            --captureScreen:Android应用程序通过它来请求SurfaceFlinger服务截取屏幕图像。

            --turnElectronBeamOff:Android应用程序通过它来请求SurfaceFlinger服务关闭屏幕。

            --turnElectronBeamOn:Android应用程序通过它来请求SurfaceFlinger服务点亮屏幕。

            --signal:Android应用程序通过它来请求SurfaceFlinger服务渲染UI,具体可以参考Android应用程序请求SurfaceFlinger服务渲染Surface的过程分析一文。

            理解了ISurfaceComposer接口的定义之后,我们再来看SurfaceFlinger服务的Binder代理对象BpSurfaceComposer的实现,如图2所示:

    图2 SurfaceFlinger服务的Binder代理对象的类关系图

            理解这个图同样需要学习Binder进程间通信机制,具体可以参考Android进程间通信(IPC)机制Binder简要介绍和学习计划这一系列的文章。

            Android应用程序获得了SurfaceFlinger服务的一个Binder代理对象,即一个BpSurfaceComposer对象之后,就可以请求SurfaceFlinger服务来创建以及渲染自己的UI了。

            接下来,我们再简单介绍一下SurfaceFlinger类的定义,如图3所示:

    图3 SurfaceFlinger类的定义

            SurfaceFlinger类有两个类型为State的成员变量mCurrentState和mDrawingState。其中,成员变量mCurrentState用来描述系统下一次要渲染的UI的状态;而mDrawingState用来描述当前正要渲染的UI的状态。

            State类用来描述一个UI状态,它有四个重要的成员变量layersSortedByZ、orientation、orientationType和freezeDisplay。其中,成员变量layersSortedByZ是一个类型为LayerVector的向量,里面保存的系统所包含的Surface,每一个Surface使用一个LayerBase对象来描述,并且它们按照 Z轴顺序来排列;成员变量orientation和orientationType的类型均为uint8_t,它们用来描述屏幕的方向; 成员变量freezeDisplay的类型也是uint8_t,用来描述屏幕是否处于被冻结状态。

            SurfaceFlinger类的成员变量mVisibleLayerSortedByZ是一个类型为sp<LayerBase>的Vector,它是用来保存SurfaceFlinger服务下一次要渲染的、处于可见状态的Surface的,它们是来自SurfaceFlinger类的成员变量mDrawingState所描述的一个State对象的成员变量layersSortedByZ的。

            SurfaceFlinger类的成员变量mGraphicPlanes是一个类型为GraphicPlane的数组,它是用来描述系统所有的显示设备的。从这个数组的大小等于1可以知道,当前Android系统只支持一个显示设备。

            GraphicPlane类有四个重要的成员变量mHw、mOrientation、mWidth和mHeight。其中,成员变量mHw指向一个DisplayHardware对象,用来描述一个硬件显示设备;成员变量mOrientation、mWidth和mHeight的类型均为int,分别用来描述一个硬件显示设备的旋转方向、宽度和高度。我们可以通过调用GraphicPlane类的成员函数setDisplayHardware和displayHardware来设备和获取一个GraphicPlane对象内部所包含的一个硬件显示设备。

            DisplayHardware类有一个重要的成员变量mNativeWindow,它是一个类型为FramebufferNativeWindow的强指针。FramebufferNativeWindow类是用来描述一个Android系统本地窗口,而这个窗口代表的是系统的硬件帧缓冲区。DisplayHardware类的成员函数flip是用来渲染系统UI的,即将后端的图形缓冲区翻转为前端的图形缓冲区,并且渲染在硬件帧缓冲区去。

           FramebufferNativeWindow类与在前面Android应用程序请求SurfaceFlinger服务创建Surface的过程分析一文中所介绍的Surface类的作用是一样的,即它是OpenGL库和Android的UI系统之间的一个桥梁。OpenGL库正是通过它的成员函数dequeueBuffer来获得一个用来填充UI数据的图形缓冲区,而通过它的成员函数queueBuffer来将一个已经填充好UI数据的图形缓冲区渲染到系统的帧缓冲区中去。

           FramebufferNativeWindow类有三个重要的成员变量fbDev、grDev和buffers。其中,成员变量fbDev和grDev分别指向一个framebuffer_device_t设备和一个alloc_device_t设备。从前面Android帧缓冲区(Frame Buffer)硬件抽象层(HAL)模块Gralloc的实现原理分析一文可以知道,framebuffer_device_t设备和一个alloc_device_t设备是由HAL模块Gralloc来提供的,它们分别用来分配图形缓冲区和渲染图形缓冲区;成员变量buffers是一个类型为NativeBuffer的数组,这个数组用来描述一个图形缓冲区堆栈,堆栈的大小为NUM_FRAME_BUFFERS,这些图形缓冲区是直接在硬件帧缓冲区中分配的,有别于Surface类所使用的图形缓冲区,因为后者所使用的图形缓冲区是在匿名共享内存分配的。

          了解了SurfaceFlinger类的重要成员变量之后,我们再来了解它的几个重要成员函数threadLoop、waitForEvent、signalEvent、handleConsoleEvents、handleTransaction、handlePageFlip、handleRepaint和postFramebuffer。

           SurfaceFlinger服务虽然是在System进程中启动的,但是它在启动的时候创建一个线程来专门负责渲染UI。为了方便描述,我们将这个线程称为UI渲染线程。UI渲染线程的执行函数就为SurfaceFlinger类的成员函数threadLoop,同时它有一个消息队列。当UI渲染线程不需要渲染UI时,它就会在SurfaceFlinger类的成员函数waitForEvent中睡眠等待,直到SurfaceFlinger服务需要执行新的UI渲染操作为止。

           SurfaceFlinger服务什么时候会需要执行新的UI渲染操作呢?当系统显示屏属性发生变化,或者应用程序窗口发生变化时,它就需要重新渲染系统的UI。这时候SurfaceFlinger服务就会从SurfaceFlinger类的成员函数waitEvent中唤醒,并且依次执行SurfaceFlinger类的成员函数handleConsoleEvents、handleTransaction、handlePageFlip、handleRepaint和postFramebuffer来具体执行渲染UI的操作。其中,成员函数handleConsoleEvents用来处理控制台事件;成员函数handleTransaction用来处理系统显示屏属性变化以及应用程序窗口属性变化;成员函数handlePageFlip用来获得应用程序窗口下一次要渲染的图形缓冲区,即设置应用程序窗口的活动图形缓冲区;成员函数handleRepaint用来重绘应用程序窗口;成员函数postFramebuffer用来将系统UI渲染到硬件帧缓冲区中去。

           我们知道,应用程序是运行在与SurfaceFlinger服务不同的进程中的,而从前面Android应用程序请求SurfaceFlinger服务渲染Surface的过程分析一文又可以知道,每当应用程序需要更新自己的UI时,它们就会通过Binder进程间通信机制来通知SurfaceFlinger服务。SurfaceFlinger服务接到这个通知之后,就会调用SurfaceFlinger类的成员函数signalEvent来唤醒UI渲染线程,以便它可以执行渲染UI的操作。注意,SurfaceFlinger服务是通过Binder线程来获得应用程序的请求的,因此,这时候SurfaceFlinger服务的UI渲染线程实际上是被Binder线程唤醒的。SurfaceFlinger类的成员函数signalEvent实际上是通过向UI渲染线程的消息队列发送一个类型为INVALIDATE的消息来唤醒UI渲染线程的。

           前面提到, SurfaceFlinger服务在在执行UI渲染操作时,需要调用SurfaceFlinger类的成员函数handleConsoleEvents来处理控制台事件。这怎么理解呢?原来,SurfaceFlinger服务在启动的时候,还会创建另外一个线程来监控由内核发出的帧缓冲区硬件事件。为了方便描述,我们将这个线程称为控制台事件监控线程。每当帧缓冲区要进入睡眠状态时,内核就会发出一个睡眠事件,这时候SurfaceFlinger服务就会执行一个释放屏幕的操作;而当帧缓冲区从睡眠状态唤醒时,内核就会发出一个唤醒事件,这时候SurfaceFlinger服务就会执行一个获取屏幕的操作。

           这样,我们就简要介绍完了SurfaceFlinger类的定义。从这些介绍可以知道:

           1. SurfaceFlinger服务通过一个GraphicPlane对象来管理系统的显示设备;

           2. SurfaceFlinger服务有三种类型的线程,它们分别是Binder线程、控制台事件监控线程和UI渲染线程;

           3. SurfaceFlinger服务是在UI渲染线程中执行渲染系统UI的操作的。

           围绕上述三个内容,再结合SurfaceFlinger服务的启动过程,接下来我们再通过以下四篇文章来系统地学习SurfaceFlinger服务的实现原理:

           1.  SurfaceFlinger服务是如何启动的?

           2.  SurfaceFlinger服务是如何通过GraphicPlane、DisplayHardware和FramebufferNativeWindow三个类来管理系统的显示设备的

           3.  SurfaceFlinger服务的三个线程的协作模型是如何的

           4.  SurfaceFlinger服务是如何在UI渲染线程中执行UI渲染操作的

           结合前面Android应用程序与SurfaceFlinger服务的关系概述和学习计划的一系列文章,以及上述四篇文章,相信我们就可以对SurfaceFlinger服务有一个清晰的认识了,敬请关注!

    老罗的新浪微博:http://weibo.com/shengyangluo,欢迎关注!

  • 相关阅读:
    jsp mysql 配置线程池
    服务端 模拟 检测 攻击。。乱写
    硕思闪客精灵 7.2 破解版
    unity UnityAwe 插件
    smartfoxserver 2x 解决 Math NAN
    unity 断点下载
    java 监听文件目录修改
    wind7 64 setup appjs
    sfs2x 修改jvm 内存
    unity ngui 解决图层问题
  • 原文地址:https://www.cnblogs.com/mfryf/p/3092056.html
Copyright © 2011-2022 走看看