Android图形系统(六)-app与SurfaceFlinge
经过上一篇的概览,我们对Android图形系统渲染流程有了一个大致的了解,这篇开始做细节分析。那么先来总结下app与SurfaceFlinger服务连接过程。
经过前面的activity 、window 、view 的分析我们大致了解了Activity的显示过程。其实Surface的创建过程与Activity的显示过程密不可分。
那么就从Activity.makeVisible 开始捋下流程:
1 Activity.makeVisible getWindowManager() 并执行addView。
2 经过WindowManagerImpl 和 WindowManagerGlobal addView , 最终创建了ViewRootImpl
3 ViewRootImpl 内部会new Surface() ,它是一个Parcelable对象,可在进程间传递,但目前仅是一个空壳,还未被赋值。
同时,通过WindowManagerGlobal.getWindowSession()获取了Session实例,准备好了与WMS通信,并且Session内有个成员变量SurfaceSession值得关注,它的初始化是在Session的windowAddedLocked方法,先埋个伏笔。
4 根据流程我们知道,最终ViewRootImpl会在走setView, 在这个方法中开始了两个流程:
requestLayout() 开启了绘制流程。
mWindowSession.addToDisplay(mWindow, mSeq, mWindowAttributes,
getHostVisibility(), mDisplay.getDisplayId(),
mAttachInfo.mContentInsets, mAttachInfo.mStableInsets,
mAttachInfo.mOutsets, mInputChannel); binder ipc 让WMS执行添加并显示window操作。
我们先来看看mWindowSession.addToDisplay,这个过程最终是在WMS执行addWindow方法:
addWindow(…){
...
//创建 WindowState , WindowState是系统层面对Window管理的一个封装类,与Window一一对应的。
WindowState win = new WindowState(...);
…
//别的都不看了,重点关注attach方法
win.attach();
...
}
//WindowState.java
void attach() {
mSession.windowAddedLocked();//mSession 是 Session
}
我们之前埋过伏笔的,windowAddedLocked创建了SurfaceSession 对象,并将当前 Session 添加到 WMS.mSessions 成员变量。SurfaceSession 的创建会调用 JNI,在 JNI 调用 nativeCreate()。
从这里开始要细说下了,这是应用程序与SurfaceFlinger建立连接的关键点:
跟踪到android_view_SurfaceSession.cpp 的nativeCreate()方法,创建了SurfaceComposerClient 对象,并且将这个对象赋值给类型为sp<SurfaceComposerClient>的智能指针mSession时,就会导致SurfaceComposerClient类的成员函数onFirstRef被调用:
void SurfaceComposerClient::onFirstRef() {
sp<ISurfaceComposer> sm(ComposerService::getComposerService());
if (sm != 0) {
sp<ISurfaceComposerClient> conn = sm->createConnection();
if (conn != 0) {
mClient = conn;
mStatus = NO_ERROR;
}
}
}
SurfaceComposerClient类的成员函数getComposerService用来获得SurfaceFlinger服务的一个代理接口.
sp<ISurfaceComposer> ComposerService::getComposerService() {
return ComposerService::getInstance().mComposerService;
}
ComposerService类是单例模式,当我们第一次调用它的静态函数getInstance的时候,它就会在构造函数中获得SurfaceFlinger服务的一个代理接口,并且保存在它的成员变量mComposerService中,同时会通过这个代理接口的成员函数getCblk来获得一块匿名共享内存mServerCblkMemory。这块匿名共享内存是由SurfaceFlinger服务创建的,用来描述系统显示屏的信息,例如,显示屏的个数、大小、方向、密度等等信息。
ComposerService::ComposerService()
: Singleton<ComposerService>() {
const String16 name("SurfaceFlinger");
while (getService(name, &mComposerService) != NO_ERROR) {
usleep(250000);
}
mServerCblkMemory = mComposerService->getCblk();
mServerCblk = static_cast<surface_flinger_cblk_t volatile *>(
mServerCblkMemory->getBase());
}
这时候sm有值了,在接着onFirstRef()往下执行:
sp<ISurfaceComposerClient> conn = sm->createConnection();
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;
}
是不是感觉特别绕,下面来简单总结下:
首先ComPoserService作为client 与 SurfaceFlinger server进行binder IPC , 获取到SurfaceFlinger创建的Client对象,它相当于是SurfaceFlinger内部对应用程序客户端的封装对象,而Client与SurfaceComposerClient又互为binder ipc的两端,SurfaceComposerClient为client端,Client为server端。
这样,应用进程成功通过SurfaceComposerClient与SurfaceFlinger建立了连接。
下篇分析app请求SurfaceFlinger创建Surface过程。
参考:
https://blog.csdn.net/Luoshengyang/article/details/7857163
https://blog.csdn.net/armwind/article/details/73436532