现在的位置: 首页 > 综合 > 正文

GUI系统之SurfaceFlinger(11)SurfaceComposerClient

2014年09月05日 ⁄ 综合 ⁄ 共 4593字 ⁄ 字号 评论关闭

文章都是通过阅读源码分析出来的,还在不断完善与改进中,其中难免有些地方理解得不对,欢迎大家批评指正。
转载请注明:From LXS. http://blog.csdn.net/uiop78uiop78/

GUI系统之SurfaceFlinger章节目录:
blog.csdn.net/uiop78uiop78/article/details/8954508

1.1.1 SurfaceComposerClient

 

图 11‑28 每个应用程序在SurfaceFlinger中都对应一个Client

 

SurfaceFlinger运行于SystemServer这一系统进程中,需要UI界面显示的应用程序则通过binder服务与它进行跨进程通信。在音频系统的学习中,每一个AudioTrack在AudioFlinger中都可以找到一个对应的Track实现。这种设计方式同样适用于显示系统,即任何有UI界面的程序都在SurfaceFlinger中有且仅有一个Client实例。

Client这个类名并没有完全表达出它的含义,因为在Android系统的很多其它地方你都可以找到同名的类。应用程序与SurfaceFlinger间的接口是ISurfaceComposerClient,Client的父类是BnSurfaceComposerClient,它是这一接口的本地端实现。

/*frameworks/native/include/gui/ISurfaceComposerClient.h*/

class ISurfaceComposerClient : public IInterface

{   …

virtual sp<ISurface>createSurface( surface_data_t* data, const String8& name, DisplayIDdisplay,

                            uint32_t w,uint32_t h, PixelFormat format, uint32_t flags) = 0;

    virtual status_t    destroySurface(SurfaceID sid) = 0;

};

接口中最重要的两个方法createSurface()和destroySurface()分别用于向SurfaceFlinger申请和销毁一个ISurface。那么既然有了Client,为什么还要再引出另一个binder对象呢?

这是因为每个SurfaceFlinger的客户程序都只会有唯一一个Client连接,但它们内部拥有的Surface数量却很可能有多个。通常情况下,同一个Activity中的UI布局共用系统分配的Surface进行绘图,但像SurfaceView这种UI组件就是特例——它独占一个Surface进行绘制。举个例子来说,如果我们制作一个带SurfaceView的视频播放器,其所在的应用程序最终就会有不止一个的Surface存在。这样设计是必须的,因为播放视频对刷新频率要求很高,采用单独的Surface既可以保证视频的流畅度,也同时能让用户的交互动作(比如触摸屏操作)及时得到响应。

Client的继承关系图如下所示:

图 11‑29 ISurfaceComposerClient的本地端实现

 

1. SurfaceFlinger::createConnection

由于Client属于匿名binder服务,外界的进程不可能直接获取到,因而首先需要借助SurfaceFlinger这一实名binder Service,源码实现如下:

sp<ISurfaceComposerClient> SurfaceFlinger::createConnection()

{

   sp<ISurfaceComposerClient> bclient;

    sp<Client>client(new Client(this));

    status_t err =client->initCheck();

    if (err == NO_ERROR) {

        bclient = client;

    }

    return bclient;

}

首先新建一个Client本地对象,initCheck初始化完成后如果没有错误的话,就可以ISurfaceComposerClient强指针返回。其中initCheck在目前版本中并没有做本质工作,它会直接返回NO_ERROR。

2. Client::createSurface

Client只是建立起了UI程序与SurfaceFlinger间的纽带,真正的图形层(Surface)创建需要另外申请,即调用Client提供的如下接口:

/*frameworks/native/services/surfaceflinger/SurfaceFlinger.cpp*/

sp<ISurface> Client::createSurface(…)

{

    class MessageCreateSurface: public MessageBase {…

        SurfaceFlinger*flinger;

        Client* client;

        …

    public:

        MessageCreateSurface(…): flinger(flinger), params(params),client(client), name(name),

             display(display), w(w), h(h), format(format), flags(flags)

        {//构造函数主要是对成员变量进行初始化

        }

        sp<ISurface>getResult() const { return result; }

        virtual bool handler(){

            result =flinger->createSurface(params, name, client, display, w, h, format, flags);

            return true;

        }

    };

 

sp<MessageBase> msg = newMessageCreateSurface(mFlinger.get(),params, name, this,

                                             display,w, h, format, flags);

    mFlinger->postMessageSync(msg); //将这一Message推送到SurfaceFlinger线程中

    return  static_cast<MessageCreateSurface*>(msg.get() )->getResult();

}

这个函数比较特别的地方,是它先在内部创建了一个MessageCreateSurface类,剩余部分代码就是围绕这个类展开的。那么MessageCreateSurface有什么作用呢?从名称上看,它应该和Message有关,其父类是MessageBase,定义在MessageQueue.h中,如下关系图所示:

图 11‑30 MessageCreateSurface

 

从这个继承图中可以大概看出一点端倪,即MessageCreateSurface是一个Message的承载体,并且内部提供了处理这条Message的handler()函数。这是不是和Java层的Handler很像?可能也是这个原因,所以其“祖谱”中有一个类取名为MessageHandler。回过头来看createSurface中的最后几行,程序将一个MessageCreateSurface对象msg发送到了SurfaceFlinger中:

mFlinger->postMessageSync(msg);

为什么要这么做呢?

大家还记不记得在进程章节讲述Message、Looper、Handler的关系时曾经举过一个例子,为了方便阅读我们再把它列出来:

“。。。

打个比方来说,某天你和朋友去健身房运动,正当你在跑步机上气喘吁吁时,旁边有个朋友跟你说:“哥们,最近手头紧,借点钱花花”。那么这时候你就有两个选择:

Ø 马上执行

这就意味着你要从跑步机上下来,问清借多少钱,然后马上打开电脑进行转账汇款

Ø 稍后执行

上面的方法在某些场合下是有用的,不过大部分情况下“借钱”这种事并不是刻不容缓的,因而你可以跟你朋友说:“借钱没问题,你先和我秘书约时间,改天我们具体谈细节”。那么在这种情况下,这个“借钱事件”就通过秘书这个MessageQueue进入了排队,所以你并不需要从跑步机上下来,中断健身运动。后期秘书会一件件通知你MessageQueue上的待办事宜(当然你也可以主动问秘书),直到“借钱事件”时你才需要和这位朋友进一步商谈。在一些场合下这样的处理方式是合情合理的。比如说健身房一小时花费是10万,而你朋友只借一百块,那么在这时处理这一事件就不合理了

这个例子在createSurface()这个场景中也是同样适用的,如下图所示:

 

图 11‑31 createSurface中的消息投递与执行

 

函数postMessageSync是SurfaceFlinger提供的一个接口,它通过mEventQueue将Msg压入队列中,并且还会进入等待状态,如下:

status_t SurfaceFlinger::postMessageSync(constsp<MessageBase>& msg, nsecs_t reltime, uint32_t flags) {

    status_t res =mEventQueue.postMessage(msg, reltime);

    if (res == NO_ERROR) {

        msg->wait();

    }

    return res;

}

MessageBase::wait()调用内部的Barrier::wait来实现等待,这意味着发送消息的线程将暂时停止执行,那么什么时候才能继续呢?显然得有人唤醒它才行。这个唤醒的地方隐藏在MessageBase::handleMessage()中,即:

/*frameworks/native/services/surfaceflinger/MessageQueue.cpp*/

void MessageBase::handleMessage(const Message&) {

    this->handler();

    barrier.open();

};

这其中的流程有点乱,我们以下图做下整理:

图 11‑32 Client::createSurface流程图

 

 

另外SurfaceFlinger中还有一个相似的消息推送函数postMessageAsync,从名称上就可以看出它是要求异步执行的,通俗来讲就是推送过后就直接返回了,无需等待执行结果,读者可以自行分析下源码。

绕了一圈后,终于轮到SurfaceFlinger工作线程来处理createSurface()了,这个函数我们在前面讲解“应用程序与BufferQueue的关系”时已经详细分析过了,这里不再赘述。

抱歉!评论已关闭.