您的位置:首页 > 产品设计 > UI/UE

GUI系统之SurfaceFlinger(10)SurfaceFlinger的启动与工作原理

2013-05-21 13:42 537 查看
文章都是通过阅读源码分析出来的,还在不断完善与改进中,其中难免有些地方理解得不对,欢迎大家批评指正。
转载请注明:From LXS. http://blog.csdn.net/uiop78uiop78/
GUI系统之SurfaceFlinger章节目录:
blog.csdn.net/uiop78uiop78/article/details/8954508

1.1.1 SurfaceFlinger的启动

SurfaceFlinger的启动和ServiceManager有点类似,它们都属于系统的底层支撑服务,必需在设备开机的早期就运行起来。
/*frameworks/base/cmds/system_server/library/System_init.cpp*/
extern "C" status_t  system_init()
{…   
   property_get("system_init.startsurfaceflinger", propBuf,"1");
    if (strcmp(propBuf,"1") == 0) {
       SurfaceFlinger::instantiate();}…
这个System_init.cpp会被编译到libsystem_server库中,然后由SystemServer在JNI层进行加载调用,从而启动包括SurfaceFlinger、SensorService等在内的系统服务。
和AudioFlinger/AudioPolicyService看到的情况一样,它调用instantiate来创建一个binder server,名称为“SurfaceFlinger”。而且强指针的特性让它在第一次被引用时会调用onFirstRef:
void SurfaceFlinger::onFirstRef()
{
    mEventQueue.init(this);//初始化事件队列
    run("SurfaceFlinger",PRIORITY_URGENT_DISPLAY);//启动一个新的业务线程
    mReadyToRunBarrier.wait();//等待新线程启动完毕
}
成员变量mEventQueue是一个MessageQueue类型的对象,我们在进程章节已经详细分析过消息队列与Looper、Handler等类的使用,大家可以先回头参考下(虽然Java层的这些类与SurfaceFlinger中用到的有一定差异,但其本质原理是一样的)。既然有消息队列,那就一定会有配套的事件处理器Handler以及循环体Looper,这些是在MessageQueue::init函数中创建的,即:
/*frameworks/native/services/surfaceflinger/MessageQueue.cpp*/
void MessageQueue::init(const sp<SurfaceFlinger>& flinger)
{
    mFlinger = flinger;
    mLooper = newLooper(true);
    mHandler = newHandler(*this);
}
也就是说这个MessageQueue类不但提供了消息队列,其内部还囊括了消息的处理机制,可以说是个“大杂烩”。那么这个Looper会在什么时候运行起来呢?显然SurfaceFlinger需要先自行创建一个新的线程来承载这一“业务”,否则就会阻塞SystemServer的主线程,这一点和AudioFlinger是有区别的。函数最后的mReadyToRunBarrier.wait()也可以证明这一点——mReadyToRunBarrier在等待一个事件,在事件没有发生前其所在的线程就会处于等待状态。这是Android系统里两个线程间的一种典型交互方式。举个例子来说,A线程将启动B线程,并且A接下来的工作会依赖于B进行。换句话说,A必顺要等到B说“好了,我已经ok”了,它才能继续往下走,否则就会出错。由此可见,SurfaceFlinger新启动的这个线程中一定还会调用mReadyToRunBarrier。
这样我们也能推断出SurfaceFlinger一定是继承自Thread线程类的,如下所示:
class SurfaceFlinger :
        publicBinderService<SurfaceFlinger>,
        …
        protected Thread
 
所以上面代码中可以调用Thread::run()方法,进而启动一个名为“SurfaceFlinger”的线程,优先级别为PRIORITY_URGENT_DISPLAY。这个优先级是在ThreadDefs.h中定义的,如下表所示:
表格 11‑6 Android系统的线程优先级定义
PriorityValueDescription
ANDROID_PRIORITY_LOWEST
19
可以使用最后的
ANDROID_PRIORITY_BACKGROUND
10
用于background tasks
ANDROID_PRIORITY_NORMAL
0
大部分线程都以这个优先级运行
ANDROID_PRIORITY_FOREGROUND
-2
用户正在交互的线程
ANDROID_PRIORITY_DISPLAY
-4
UI主线程
ANDROID_PRIORITY_URGENT_DISPLAY
-8
这个值由HAL_PRIORITY_URGENT_DISPLAY来指定,当前版本中是-8。只在部分紧急状态下使用
ANDROID_PRIORITY_AUDIO
-16
正常情况下的声音线程
ANDROID_PRIORITY_URGENT_AUDIO
-19
声音线程(通常情况不用)
ANDROID_PRIORITY_HIGHEST
-20
最高优先级,禁止使用
ANDROID_PRIORITY_DEFAULT
0
默认情况下就是ANDROID_PRIORITY_NORMAL
ANDROID_PRIORITY_MORE_FAVORABLE
-1
在上述优先级的基础上,用于加大优先级
ANDROID_PRIORITY_LESS_FAVORABLE
+1
在上述优先级的基础上,用于减小优先级
 
数值越大的,优先级越小。因为各等级间的数值并不是连续的,我们可以通过ANDROID_PRIORITY_MORE_FAVORABLE(-1)来适当地提高优先级,或者是利用ANDROID_PRIORITY_LESS_FAVORABLE(+1)来降低优先级。
由此可见,SurfaceFlinger工作线程所采用的优先级是相对较高的。这样做是必然的,因为屏幕显示无疑是人机交互中最直观的用户体验,任何滞后的响应速度都将大大降低产品的吸引力。
在执行了run()以后,Thread会自动调用threadLoop()接口,即:
bool SurfaceFlinger::threadLoop()
{
    waitForEvent();
    return true;
}
相当简洁的两句话,所有SurfaceFlinger接下来要执行的工作都涵括在这里了。其中waitForEvent()是SurfaceFlinger中的成员函数,它进一步调用mEventQueue.waitMessage():
void MessageQueue::waitMessage() {
    do {
       IPCThreadState::self()->flushCommands();
        int32_t ret =mLooper->pollOnce(-1);
        switch (ret) {
            caseALOOPER_POLL_WAKE:
            caseALOOPER_POLL_CALLBACK:
                continue;
            caseALOOPER_POLL_ERROR:
               ALOGE("ALOOPER_POLL_ERROR");
            caseALOOPER_POLL_TIMEOUT:
                // timeout(should not happen)
                continue;
            default:
                // should nothappen
               ALOGE("Looper::pollOnce() returned unknown status %d", ret);
                continue;
        }
    } while (true);
}
可以看到程序在这里进入了一个死循环,而且即便pollOnce的执行结果是ALOOPER_POLL_TIMEOUT,也同样不会跳出循环。这是Android系统在对待系统级严重错误时的一种普遍态度——一旦发生,就没救了,听天由命吧。。。
下面这句将在内部调用MessageQueue::mHandler来处理消息:
mLooper->pollOnce(-1);
注意pollOnce函数同样使用了一个死循环,它不断地取消息进行处理,关系如下:


图 11‑27 SurfaceFlinger中的消息循环机制
 
实际上SurfaceFlinger中的MessageQueue类不应该叫这个名字,因为会和我们传统的消息队列产生混淆和歧义。变量mEventQueue是消息循环处理机制的管理者,其下包含了一个Looper和一个Handler。Looper采用的是/frameworks/native/libs/utils/Looper.cpp中的实现,SurfaceFlinger没有重新定义这个类。Looper中的mMessageEnvelope才是真正存储消息的地方。
太绕了,再好的设计也应该考虑可读性L
这样子就构建了一个完整的循环消息处理框架,SurfaceFlinger就是基于这个框架完成来自系统中各个程序的显示请求的。大家可能会有疑问,mHandler是由MessageQueue在init()中直接通过newHandler()生成的,这样的话如何能处理特定的SurfaceFlinger消息请求呢?个人感觉有这个困惑也是由于Handler类取名不当引起的。实际上此Handler并非我们经常看到的那个Handler,这里的Handler是MessageQueue中自定义的一个事件处理器,也就是说它是专门为SurfaceFlinger设计的。
/*frameworks/native/services/surfaceflinger/MessageQueue.cpp*/
void MessageQueue::Handler::handleMessage(const Message&message) {
    switch (message.what) {
        case INVALIDATE:
           android_atomic_and(~eventMaskInvalidate, &mEventMask);
           mQueue.mFlinger->onMessageReceived(message.what);
            break;
        case REFRESH:
           android_atomic_and(~eventMaskRefresh, &mEventMask);
           mQueue.mFlinger->onMessageReceived(message.what);
            break;
    }
}
如上代码段所示,mHandler当收到INVALIDATE和REFRESH请求时,进一步回调了SurfaceFlinger中的onMessageReceived。等于是绕了一个大圈,又回到SurfaceFlinger中了。       
我们到目前为止还是没看到SurfaceFlinger是如何通知SystemServer线程解除等待的。这个工作是在下面的函数完成的:
status_t SurfaceFlinger::readyToRun()
{…
    mReadyToRunBarrier.open();//好了,现在可以解禁线程A了
}
函数readyToRun是在一个线程进入run循环前调用的,它为SurfaceFlinger的正常工作提供了各种必要的基础。我们在后续小节还会看到其中的更多内容,这里先分析与消息处理有关的部分。前面所说的mReadyToRunBarrier果然在这里又被调用了,open()是告诉所有正在等待的线程可以继续运行了。Barrier类内部实际上也是使用了Condition::broadcast()、Condition::wait()等常规互斥方法,只是加了一层封装而已。
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: