当前位置:操作系统 > 安卓/Android >>

Android系统Surface制的SurfaceFlinger服务的线程模型分析

   在前面两篇文章中,我们分析了SurfaceFlinger服务的启动过程以及SurfaceFlinger服务初始化硬件帧缓冲区的过程。从这两个过程可以知道,SurfaceFlinger服务在启动的过程中,一共涉及到了三种类型的线程,它们分别是Binder线程、UI渲染线程和控制台事件监控线程。在本文中,我们就将详细分SurfaceFlinger服务的线程模型,即上述三种类型的线程是如何运行和交互的。

        从Android系统Surface制的SurfaceFlinger服务的启动过程分析一文可以知道,SurfaceFlinger服务是在System进程的主线程中启动的。System进程的主线程在启动系统的关键服务之前,会先启动一个Binder线程池。这样运行在System进程中的系统关系服务就可以与其它进程执行Binder进程间通信了。SurfaceFlinger服务虽然是由System进程的主线程来负责启动的,但是最终它会运行在一个独立的线程中。我们将这个独立的线程称为UI渲染线程,因为它负责渲染系统的UI。

        从Android系统Surface制的SurfaceFlinger服务对帧缓冲区(Frame Buffer)的管理分析一文可以知道,SurfaceFlinger服务的UI渲染线程的启动的时候,会对系统的硬件帧缓冲区进行初始化。在初始化的过程,又会创建另外一个线程来监控硬件帧缓冲区的睡眠/唤醒状态切换事件。为了方便描述,我们这个线程称称为控制台事件监控线程。

        上述的三种类型的线程的启动顺序,可以通过图1来描述,如下所示:

 

图1 SurfaceFlinger服务的线程模型

       从图1就可以清楚地看到,System进程的主线程负责启动Binder线程池,以及UI渲染线程,而UI渲染线程又负责启动控制台事件监控线程。在这三种类型的线程中,UI渲染线程是主角,Binder线程和控制台事件监控线程是配角。Binder线程池是为了让其它进程,例如Android应用程序进程,可以与SurfaceFlinger服务进行Binder进程间通信的,有一部分通信所执行的操作便是让UI渲染线程更新系统的UI。控制台事件监控线程是为了监控硬件帧缓冲区的睡眠/唤醒状态切换事件的。一旦硬件帧缓冲区要进入睡眠或者唤醒状态,控制台事件监控线程都需要通知UI渲染线程,以便UI渲染线程可以执行关闭或者启动显示屏的操作。

       接下来,为了弄清楚SurfaceFlinger服务的线程模型,我们就首先简要分析UI渲染线程的运行模型,接着再分析Binder线程与UI渲染线程的交互过程,最后分析控制台事件监控线程与UI渲染线程的交互过程。

       1. UI渲染线程的运行模型

       在前面Android系统Surface机制的SurfaceFlinger服务简要介绍和学习计划一文中提到,SurfaceFlinger服务的UI渲染线程有一个消息队列。当消息队列为空时,SurfaceFlinger服务的UI渲染线程就会进入睡眠等待状态。一旦SurfaceFlinger服务的Binder线程接收到其它进程发送过来的渲染UI的请求时,它就会往SurfaceFlinger服务的UI渲染线程的消息队列中发送一个消息,以便可以将SurfaceFlinger服务的UI渲染线程唤醒起来执行渲染的操作。同样,一旦SurfaceFlinger服务的控制台事件监控线程发现硬件帧缓冲区即将要进入睡眠或者唤醒状态时,它就会往SurfaceFlinger服务的UI渲染线程的消息队列中发送一个消息,以便SurfaceFlinger服务的UI渲染线程可以执行冻结或者解冻显示屏的操作。

      从前面Android系统Surface制的SurfaceFlinger服务的启动过程分析一文又可以知道,SurfaceFlinger服务的UI渲染线程是以SurfaceFlinger类的成员函数threadLoop为线程执行体的,即SurfaceFlinger服务的UI渲染线程会不断地循环执行SurfaceFlinger类的成员函数threadLoop。接下来,我们就通过SurfaceFlinger类的成员函数threadLoop的实现来分析SurfaceFlinger服务的UI渲染线程的运行模型,如下所示:


[cpp] 
bool SurfaceFlinger::threadLoop() 

    waitForEvent(); 
 
    // check for transactions 
    if (UNLIKELY(mConsoleSignals)) { 
        handleConsoleEvents(); 
    } 
 
    if (LIKELY(mTransactionCount == 0)) { 
        // if we're in a global transaction, don't do anything. 
        const uint32_t mask = eTransactionNeeded | eTraversalNeeded; 
        uint32_t transactionFlags = getTransactionFlags(mask); 
        if (LIKELY(transactionFlags)) { 
            handleTransaction(transactionFlags); 
        } 
    } 
 
    // post surfaces (if needed) 
    handlePageFlip(); 
 
    const DisplayHardware& hw(graphicPlane(0).displayHardware()); 
    if (LIKELY(hw.canDraw() && !isFrozen())) { 
 
#ifdef USE_COMPOSITION_BYPASS 
        if (handleBypassLayer()) { 
            unlockClients(); 
            return true; 
        } 
#endif 
 
        // repaint the framebuffer (if needed) 
        const int index = hw.getCurrentBufferIndex(); 
        GraphicLog& logger(GraphicLog::getInstance()); 
 
        logger.log(GraphicLog::SF_REPAINT, index); 
        handleRepaint(); 
 
        // inform the h/w that we're done compositing 
        logger.log(GraphicLog::SF_COMPOSITION_COMPLETE, index); 
        hw.compositionComplete(); 
 
        logger.log(GraphicLog::SF_SWAP_BUFFERS, index); 
        postFramebuffer(); 
 
        logger.log(GraphicLog::SF_REPAINT_DONE, index); 
    } else { 
        // pretend we did the post 
        hw.compositionComplete(); 
        usleep(16667); // 60 fps period 
    } 
    return true; 

        这个函数定义在文件frameworks/base/services/surfaceflinger/SurfaceFlinger.cpp中。
        从前面Android应用程序请求SurfaceFlinger服务渲染Surface的过程分析一文可以知道,SurfaceFlinger类的成员函数threadLoop的工作过程如下所示:

        1. 调用SurfaceFlinger类的成员函数waitForEvent中检查SurfaceFlinger服务的UI渲染线程的消息队列是否为空。如果不为空,那么就会马上返回来执行其它的操作,否则的话,SurfaceFlinger服务的UI渲染线程就会进入睡眠等状态,直到被SurfaceFlinger服务的Binder线程或者控制台事件监控线程唤醒为止。

        2. 当SurfaceFlinger服务的UI渲染线程被控制台事件监控线程唤醒时,SurfaceFlinger类的成员变量mConsoleSignals的值就会不等于0。在这种情况下,SurfaceFlinger类的成员函数threadLoop就会调用另外一个成员函数handleConsoleEvents来处理控制台事件。后面在分析SurfaceFlinger服务的UI渲染线程和控制台事件监控线程的交互过程时,我们再分析这个成员函数的实现。

        3. SurfaceFlinger类的成员变量mTransactionCount用来描述SurfaceFlinger服务是否正在执行事务。如果SurfaceFlinger服务正在执行事务,那么SurfaceFlinger类的成员变量mTransactionCount的值就会大于0。怎么理解SurfaceFlinger服务所执行的事务是什么呢?这些事务是用来处理

补充:移动开发 , Android ,
CopyRight © 2012 站长网 编程知识问答 www.zzzyk.com All Rights Reserved
部份技术文章来自网络,