资源预览内容
第1页 / 共14页
第2页 / 共14页
第3页 / 共14页
第4页 / 共14页
第5页 / 共14页
第6页 / 共14页
第7页 / 共14页
第8页 / 共14页
第9页 / 共14页
第10页 / 共14页
亲,该文档总共14页,到这儿已超出免费预览范围,如果喜欢就下载吧!
资源描述
-Android系统Surface机制的SurfaceFlinger效劳的线程模型分析在前面两篇文章中,我们分析了SurfaceFlinger效劳的启动过程以及SurfaceFlinger效劳初始化硬件帧缓冲区的过程。从这两个过程可以知道,SurfaceFlinger效劳在启动的过程中,一共涉及到了三种类型的线程,它们分别是Binder线程、UI渲染线程和控制台事件监控线程。在本文中,我们就将详细分SurfaceFlinger效劳的线程模型,即上述三种类型的线程是如何运行和交互的。 从 一文可以知道,SurfaceFlinger效劳是在System进程的主线程中启动的。System进程的主线程在启动系统的关键效劳之前,会先启动一个Binder线程池。这样运行在System进程中的系统关系效劳就可以与其它进程执行Binder进程间通信了。SurfaceFlinger效劳虽然是由System进程的主线程来负责启动的,但是最终它会运行在一个独立的线程中。我们将这个独立的线程称为UI渲染线程,因为它负责渲染系统的UI。 从 一文可以知道,SurfaceFlinger效劳的UI渲染线程的启动的时候,会对系统的硬件帧缓冲区进展初始化。在初始化的过程,又会创立另外一个线程来监控硬件帧缓冲区的睡眠/唤醒状态切换事件。为了方便描述,我们这个线程称称为控制台事件监控线程。 上述的三种类型的线程的启动顺序,可以通过图1来描述,如下所示:从图1就可以清楚地看到,System进程的主线程负责启动Binder线程池,以及UI渲染线程,而UI渲染线程又负责启动控制台事件监控线程。在这三种类型的线程中,UI渲染线程是主角,Binder线程和控制台事件监控线程是配角。Binder线程池是为了让其它进程,例如Android应用程序进程,可以与SurfaceFlinger效劳进展Binder进程间通信的,有一局部通信所执行的操作便是让UI渲染线程更新系统的UI。控制台事件监控线程是为了监控硬件帧缓冲区的睡眠/唤醒状态切换事件的。一旦硬件帧缓冲区要进入睡眠或者唤醒状态,控制台事件监控线程都需要通知UI渲染线程,以便UI渲染线程可以执行关闭或者启动显示屏的操作。 接下来,为了弄清楚SurfaceFlinger效劳的线程模型,我们就首先简要分析UI渲染线程的运行模型,接着再分析Binder线程与UI渲染线程的交互过程,最后分析控制台事件监控线程与UI渲染线程的交互过程。 1. UI渲染线程的运行模型 在前面 一文中提到,SurfaceFlinger效劳的UI渲染线程有一个消息队列。当消息队列为空时,SurfaceFlinger效劳的UI渲染线程就会进入睡眠等待状态。一旦SurfaceFlinger效劳的Binder线程接收到其它进程发送过来的渲染UI的请求时,它就会往SurfaceFlinger效劳的UI渲染线程的消息队列中发送一个消息,以便可以将SurfaceFlinger效劳的UI渲染线程唤醒起来执行渲染的操作。同样,一旦SurfaceFlinger效劳的控制台事件监控线程发现硬件帧缓冲区即将要进入睡眠或者唤醒状态时,它就会往SurfaceFlinger效劳的UI渲染线程的消息队列中发送一个消息,以便SurfaceFlinger效劳的UI渲染线程可以执行冻结或者解冻显示屏的操作。 从前面 一文又可以知道,SurfaceFlinger效劳的UI渲染线程是以SurfaceFlinger类的成员函数threadLoop为线程执行体的,即SurfaceFlinger效劳的UI渲染线程会不断地循环执行SurfaceFlinger类的成员函数threadLoop。接下来,我们就通过SurfaceFlinger类的成员函数threadLoop的实现来分析SurfaceFlinger效劳的UI渲染线程的运行模型,如下所示:cpp view plain copy 在CODE上查看代码片派生到我的代码片bool SurfaceFlinger:threadLoop() waitForEvent(); / check for transactions if (UNLIKELY(mConsoleSignals) handleConsoleEvents(); if (LIKELY(mTransactionCount = 0) / if were in a global transaction, dont 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_POSITION_BYPASS if (handleBypassLayer() unlockClients(); return true; #endif / repaint the framebuffer (if needed) const int inde* = hw.getCurrentBufferInde*(); GraphicLog& logger(GraphicLog:getInstance(); logger.log(GraphicLog:SF_REPAINT, inde*); handleRepaint(); / inform the h/w that were done positing logger.log(GraphicLog:SF_POSITION_PLETE, inde*); hw.positionplete(); logger.log(GraphicLog:SF_SWAP_BUFFERS, inde*); postFramebuffer(); logger.log(GraphicLog:SF_REPAINT_DONE, inde*); else / pretend we did the post hw.positionplete(); usleep(16667); / 60 fps period return true; 这个函数定义在文件frameworks/base/services/surfaceflinger/SurfaceFlinger.cpp中。 从前面 一文可以知道,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效劳所执行的事务是什么呢?这些事务是用来处理系统的显示属性的。这些属性划分为两种类型。一种类型是与整个显示屏属性相关的,例如屏幕旋转方向发生了变化,另一外类型是与*一个应用程序的Surface相关的,例如*一个Surface的大小或者Z轴位置发生了变化。一般来说,每当系统的显示属性发生了变化的时候,SurfaceFlinger效劳的UI渲染线程都需要马上刷新系统UI,以便可以反映真实情况。但是,为了减少屏幕的闪烁,有时候可以将多个属性变化组合成一个事务来刷新系统UI。例如,我们可以在修改了一个Surface的大小和Z轴位置之后,才要求SurfaceFlinger效劳的UI渲染线程去刷新系统UI,这样就可以减少一个刷新系统UI的操作。因此,只有当SurfaceFlinger类的成员变量mTransactionCount的值的等于0的时候,SurfaceFlinger类的成员函数threadLoop才会判断系统的显示属性是否发生了变化。如果发生了变化,则就会调用另外一个成员函数handleTransaction来进一步处理。在接下来的一篇文章中分析SurfaceFlinger效劳的UI渲染过程时,我们就详细分析这个成员函数的实现。 4. SurfaceFlinger效劳的UI渲染线程接下来调用SurfaceFlinger类的成员函数handlePageFlip来通知各个应用程序的Surface将接下来要渲染的图形缓冲区设置为当前激活的图形缓冲区,以便接下来可以渲染到硬件帧缓冲区中去。我们同样会在接下来的一篇文章中分析SurfaceFlinger效劳的UI渲染过程时,详细分析这个成员函数的实现。 5. 如果SurfaceFlinger效劳的UI渲染线程目前只有一个Surface需要渲染,并且SurfaceFlinger类在编译时,指定了USE_POSITION_BYPASS宏,则SurfaceFlinger类的成员函数threadLoop就会直接调用另外一个成员函数handleBypassLayer来将这个Surface直接渲染到硬件帧缓冲区中去。这是一个优化操作,防止执行接下来的Surface合成操作。 6. 如果SurfaceFli
网站客服QQ:2055934822
金锄头文库版权所有
经营许可证:蜀ICP备13022795号 | 川公网安备 51140202000112号