概述
文章都是通过阅读源码分析出来的,还在不断完善与改进中,其中难免有些地方理解得不对,欢迎大家批评指正。
转载请注明: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的关系”时已经详细分析过了,这里不再赘述。
最后
以上就是文艺蜻蜓为你收集整理的GUI系统之SurfaceFlinger(11)SurfaceComposerClient的全部内容,希望文章能够帮你解决GUI系统之SurfaceFlinger(11)SurfaceComposerClient所遇到的程序开发问题。
如果觉得靠谱客网站的内容还不错,欢迎将靠谱客网站推荐给程序员好友。
发表评论 取消回复