Android系统Su易做图ce制的Su易做图ceFlinger服务的线程模型分析
在前面两篇文章中,我们分析了Su易做图ceFlinger服务的启动过程以及Su易做图ceFlinger服务初始化硬件帧缓冲区的过程。从这两个过程可以知道,Su易做图ceFlinger服务在启动的过程中,一共涉及到了三种类型的线程,它们分别是Binder线程、UI渲染线程和控制台事件监控线程。在本文中,我们就将详细分Su易做图ceFlinger服务的线程模型,即上述三种类型的线程是如何运行和交互的。
从Android系统Su易做图ce制的Su易做图ceFlinger服务的启动过程分析一文可以知道,Su易做图ceFlinger服务是在System进程的主线程中启动的。System进程的主线程在启动系统的关键服务之前,会先启动一个Binder线程池。这样运行在System进程中的系统关系服务就可以与其它进程执行Binder进程间通信了。Su易做图ceFlinger服务虽然是由System进程的主线程来负责启动的,但是最终它会运行在一个独立的线程中。我们将这个独立的线程称为UI渲染线程,因为它负责渲染系统的UI。
从Android系统Su易做图ce制的Su易做图ceFlinger服务对帧缓冲区(Frame Buffer)的管理分析一文可以知道,Su易做图ceFlinger服务的UI渲染线程的启动的时候,会对系统的硬件帧缓冲区进行初始化。在初始化的过程,又会创建另外一个线程来监控硬件帧缓冲区的睡眠/唤醒状态切换事件。为了方便描述,我们这个线程称称为控制台事件监控线程。
上述的三种类型的线程的启动顺序,可以通过图1来描述,如下所示:
图1 Su易做图ceFlinger服务的线程模型
从图1就可以清楚地看到,System进程的主线程负责启动Binder线程池,以及UI渲染线程,而UI渲染线程又负责启动控制台事件监控线程。在这三种类型的线程中,UI渲染线程是主角,Binder线程和控制台事件监控线程是配角。Binder线程池是为了让其它进程,例如Android应用程序进程,可以与Su易做图ceFlinger服务进行Binder进程间通信的,有一部分通信所执行的操作便是让UI渲染线程更新系统的UI。控制台事件监控线程是为了监控硬件帧缓冲区的睡眠/唤醒状态切换事件的。一旦硬件帧缓冲区要进入睡眠或者唤醒状态,控制台事件监控线程都需要通知UI渲染线程,以便UI渲染线程可以执行关闭或者启动显示屏的操作。
接下来,为了弄清楚Su易做图ceFlinger服务的线程模型,我们就首先简要分析UI渲染线程的运行模型,接着再分析Binder线程与UI渲染线程的交互过程,最后分析控制台事件监控线程与UI渲染线程的交互过程。
1. UI渲染线程的运行模型
在前面Android系统Su易做图ce机制的Su易做图ceFlinger服务简要介绍和学习计划一文中提到,Su易做图ceFlinger服务的UI渲染线程有一个消息队列。当消息队列为空时,Su易做图ceFlinger服务的UI渲染线程就会进入睡眠等待状态。一旦Su易做图ceFlinger服务的Binder线程接收到其它进程发送过来的渲染UI的请求时,它就会往Su易做图ceFlinger服务的UI渲染线程的消息队列中发送一个消息,以便可以将Su易做图ceFlinger服务的UI渲染线程唤醒起来执行渲染的操作。同样,一旦Su易做图ceFlinger服务的控制台事件监控线程发现硬件帧缓冲区即将要进入睡眠或者唤醒状态时,它就会往Su易做图ceFlinger服务的UI渲染线程的消息队列中发送一个消息,以便Su易做图ceFlinger服务的UI渲染线程可以执行冻结或者解冻显示屏的操作。
从前面Android系统Su易做图ce制的Su易做图ceFlinger服务的启动过程分析一文又可以知道,Su易做图ceFlinger服务的UI渲染线程是以Su易做图ceFlinger类的成员函数threadLoop为线程执行体的,即Su易做图ceFlinger服务的UI渲染线程会不断地循环执行Su易做图ceFlinger类的成员函数threadLoop。接下来,我们就通过Su易做图ceFlinger类的成员函数threadLoop的实现来分析Su易做图ceFlinger服务的UI渲染线程的运行模型,如下所示:
[cpp]
bool Su易做图ceFlinger::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 su易做图ces (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/su易做图ceflinger/Su易做图ceFlinger.cpp中。
从前面Android应用程序请求Su易做图ceFlinger服务渲染Su易做图ce的过程分析一文可以知道,Su易做图ceFlinger类的成员函数threadLoop的工作过程如下所示:
1. 调用Su易做图ceFlinger类的成员函数waitForEvent中检查Su易做图ceFlinger服务的UI渲染线程的消息队列是否为空。如果不为空,那么就会马上返回来执行其它的操作,否则的话,Su易做图ceFlinger服务的UI渲染线程就会进入睡眠等状态,直到被Su易做图ceFlinger服务的Binder线程或者控制台事件监控线程唤醒为止。
2. 当Su易做图ceFlinger服务的UI渲染线程被控制台事件监控线程唤醒时,Su易做图ceFlinger类的成员变量mConsoleSignals的值就会不等于0。在这种情况下,Su易做图ceFlinger类的成员函数threadLoop就会调用另外一个成员函数handleConsoleEvents来处理控制台事件。后面在分析Su易做图ceFlinger服务的UI渲染线程和控制台事件监控线程的交互过程时,我们再分析这个成员函数的实现。
3. Su易做图ceFlinger类的成员变量mTransactionCount用来描述Su易做图ceFlinger服务是否正在执行事务。如果Su易做图ceFlinger服务正在执行事务,那么Su易做图ceFlinger类的成员变量mTransactionCount的值就会大于0。怎么理解Su易做图ceFlinger服务所执行的事务是什么呢?这些事务是用来处理
补充:移动开发 , Android ,