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

Android系统Surface机制的SurfaceFlinger服务渲染应用程序UI的过程分析

   在前面的一系列文章中,我们学习了Android应用程序与SurfaceFlinger服务的关系,以及SurfaceFlinger服务的启动过程、初始化硬件帧缓冲区的过程、线程模型。SurfaceFlinger服务所做的一切都是为了给Android应用程序提服务的,即为Android应用程序渲染它们的UI。在本文中,我们就详细分析SurfaceFlinger服务渲染Android应用程序UI的过程。

        从前面Android系统Surface制的SurfaceFlinger服务的线程模型分析一文可以知道,SurfaceFlinger服务是通过它的UI渲染线程来将应用程序的UI渲染到硬件帧缓冲区中去的,因此,接下来我们就通过分析SurfaceFlinger服务的UI渲染线程的执行过程来分应用程序UI的渲染过程,这个过程如图1所示。

 

图1 SurfaceFlinger服务渲染应用程序UI的示意图

        从图1就可以看出,SurfaceFlinger服务的UI渲染线程的执行过程如下所示:

        1. 调用SurfaceFlinger类的成员函数handleConsoleEvents来处理控制台事件。

        2. 调用SurfaceFlinger类的成员函数handleTransaction来处理系统显示屏以及应用程序窗口的属性变化,例如大小、旋转方向变化等。

        3. 调用SurfaceFlinger类的成员函数handlePageFlip来让各个应用程序窗口设置它们当前所要渲染的图形缓冲区。

        4. 如果SurfaceFlinger服务在编译的时候指定了USE_COMPOSITION_BYPASS宏,并且当前需要渲染的应用程序窗口只有一个,那么就会调用SurfaceFlinger类的成员函数handleBypassLayer来直接将这个应用程序窗口的图形缓冲区渲染到硬件帧缓冲区中去,否则的话,就要调用SurfaceFlinger类的成员函数handleRepaint来合成所有的应用程序窗口的图形缓冲区到一个主图形缓冲区中去。

        5. 调用SurfaceFlinger类的成员函数postFramebuffer将前面得到的主图形缓冲区渲染到硬件帧缓冲区中去。

        前面Android系统Surface制的SurfaceFlinger服务的线程模型分析一文中,我们已经分析过第1步的实现了,而通过前面Android应用程序与SurfaceFlinger服务的关系概述和学习计划这一系列文章的学习,我们也已经了解了应用程序窗口的图形缓冲区的创建过程,因此,接下来我们就在这些知识的基础上来详细分析第2步到第5的实现,即分别分析SurfaceFlinger类的成员函数handleTransaction、handlePageFlip、handleBypassLayer和postFramebuffer的实现。

       1. handleTransaction

       SurfaceFlinger类的成员函数handleTransaction是用来处理系统显示屏以及应用程序窗口的属性变化的,这个过程如图2所示。

 

图2 系统显示屏以及应用程序窗口的属性变化处理过程

         这个过程可以分为6个步骤,接下来我们就详细分析每一个步骤。

         Step 1. SurfaceFlinger.handleTransaction

[cpp] 
void SurfaceFlinger::handleTransaction(uint32_t transactionFlags) 

    Vector< sp<LayerBase> > ditchedLayers; 
 
    /*
     * Perform and commit the transaction
     */ 
 
    { // scope for the lock 
        Mutex::Autolock _l(mStateLock); 
        const nsecs_t now = systemTime(); 
        mDebugInTransaction = now; 
        handleTransactionLocked(transactionFlags, ditchedLayers); 
        mLastTransactionTime = systemTime() - now; 
        mDebugInTransaction = 0; 
        // here the transaction has been committed 
    } 
 
    /*
     * Clean-up all layers that went away
     * (do this without the lock held)
     */ 
    const size_t count = ditchedLayers.size(); 
    for (size_t i=0 ; i<count ; i++) { 
        if (ditchedLayers[i] != 0) { 
            //LOGD("ditching layer %p", ditchedLayers[i].get()); 
            ditchedLayers[i]->ditch(); 
        } 
    } 
}  
        这个函数定义在文件frameworks/base/services/surfaceflinger/SurfaceFlinger.cpp中。
        SurfaceFlinger类的成员函数handleTransaction是通过调用另外一个成员函数handleTransactionLocked来处理系统显示屏以及应用程序窗口的属性变化的,而SurfaceFlinger类的成员函数handleTransactionLocked在处理完成系统显示屏以及应用程序窗口的属性变化之后,会返回系统中那些已经销毁了的应用程序窗口。

        从Android应用程序与SurfaceFlinger服务的关系概述和学习计划这一系列文章可以知道,在SurfaceFlinger服务这一侧,应用程序窗口一般是使用一个Layer对象来描述的,又由于Layer类是从LayerBase类继承下来的,因此,我们可以那些已经销毁了的应用程序窗口保存在一个类型为sp<LayerBase>的向量ditchedLayers中。

        SurfaceFlinger类的成员函数handleTransaction最后就调用保存在向量ditchedLayers中的每一个LayerBase对象的成员函数dtich来执行被销毁的应用程序窗口的清理操作,接下来我们就继续分析SurfaceFlinger类的成员函数handleTransactionLocked,看看它是如何处理系统显示屏以及应用程序窗口的属性变化的。

        Step 2. SurfaceFlinger.handleTransactionLocked

        SurfaceFlinger类的成员函数handleTransactionLocked定义在文件rameworks/base/services/surfaceflinger/SurfaceFlinger.cpp中,我们分三段来阅读:

[cpp]
void SurfaceFlinger::handleTransactionLocked( 
        uint32_t transactionFlags, Vector< sp<LayerBase> >& ditchedLayers) 

    const LayerVector& currentLayers(mCurrentState.layersSortedByZ); 
    const size_t count = currentLayers.size(); 
 
    /*
     * Traversal of the children
     * (perform the transaction for each of them if needed)
     */ 
 
    const bool layersNeedTransaction = transactionFlags & eTraversalNeeded; 
    if (layersNeedTransaction) { 
        for (size_t i=0 ; i<count ; i++) { 
            const sp<LayerBase>& layer = currentLayers[i]; 
            uint32_t trFlags = layer->getTransactionFlags(eTransactionNeeded); 
            if (!trFlags) continue; 
 
            const uint32_t flags = layer->doTransaction(0); 
            if (flags & Layer::eVisibleRegion) 
                mVisibleRegionsDirty = true; 
        } 
    } 
        这段代码用来处理应用程序窗口的属性变化

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