接上篇,WindowManager addView流程来:
ViewRootImpl走setView 我们已经讲了mWindowSession.addToDisplay这条线,app与SurfaceFlinger服务建立了连接,下面我们接着看另外一条线: requestLayout()。
前面我们讲了,requestLayout()开启了绘制流程,具体流程如下图所示:
前三步不啰嗦了,不了解的可以去看View绘制篇,这里我们从WMS中relayoutWindow开始说起:
//WindowManagerService
public int relayoutWindow(Session session, IWindow client,
WindowManager.LayoutParams attrs, int requestedWidth,
int requestedHeight, int viewVisibility, boolean insetsPending,
Rect outFrame, Rect outContentInsets, Rect outVisibleInsets,
Configuration outConfig, Surface outSurface) {
......
synchronized(mWindowMap) {
WindowState win = windowForClientLocked(session, client, false);
......
Surface surface = win.createSurfaceLocked();
if (surface != null) {
outSurface.copyFrom(surface);
......
}
......
}
调用WindowState对象win的成员函数createSurfaceLocked来为它创建一个Surface。如果这个Surface已创建成功,就会将它的内容拷贝到输出参数outSurface,这个outSurface就是从ViewRootImpl调用relayoutWindow通过参数带进来的空Surface对象,以便可以将它返回给应用程序进程处理。
先来看看win.createSurfaceLocked()
private final class WindowState implements WindowManagerPolicy.WindowState {
......
Surface mSurface;
......
Surface createSurfaceLocked() {
…...
mSurface = new Surface(
mSession.mSurfaceSession, mSession.mPid,
mAttrs.getTitle().toString(),
0, w, h, mAttrs.format, flags);
......
return mSurface;
}
......
}
简单理解就是new 了一个java层Surface,然后初始化了应用程序窗口的各种属性:包括pid、标题、像素格式、宽、高、图形缓冲区属性标志等。
那么接着我们来看下Surface这个对象:
public class Surface implements Parcelable {
private int mSurfaceControl;
private Canvas mCanvas;
private String mName;
......
public Surface(SurfaceSession s,
int pid, String name, int display, int w, int h, int format, int flags)
throws OutOfResourcesException {
......
mCanvas = new CompatibleCanvas();
init(s,pid,name,display,w,h,format,flags);
mName = name;
}
......
private native void init(SurfaceSession s,
int pid, String name, int display, int w, int h, int format, int flags)
throws OutOfResourcesException;
......
public void copyFrom(SurfaceControl other) {
if (other == null) {
throw new IllegalArgumentException("other must not be null");
}
long surfaceControlPtr = other.mNativeObject;
if (surfaceControlPtr == 0) {
throw new NullPointerException(
"SurfaceControl native object is null. Are you using a released SurfaceControl?");
}
long newNativeObject = nativeCreateFromSurfaceControl(surfaceControlPtr);
synchronized (mLock) {
if (mNativeObject != 0) {
nativeRelease(mNativeObject);
}
setNativeObjectLocked(newNativeObject);
}
}
Surface类有三个成员变量mSurfaceControl、mCanvas和mName,它们的类型分别是int、Canvas和mName,其中,mSurfaceControl保存的是在C++层的一个SurfaceControl对象的地址值,mCanvas用来描述一块类型为CompatibleCanvas的画布,mName用来描述当前正在创建的一个绘图表面的名称。这里我们主要关注成员变量mSurfaceControl所关联的C++层的SurfaceControl对象是如何创建的。
Surface类的构造函数是通过调用另外一个成员函数init来创建与成员变量mSurfaceControl所关联的C++层的SurfaceControl对象的。Surface类的成员函数init是一个JNI方法,它是由C++层的函数Surface_init来实现的,如下所示:
static void Surface_init(JNIEnv*env, jobject clazz, jobject session, jint pid, jstring jname, jint dpy, jint w, jint h, jint format, jintflags) {
//从 SurfaceSession 对象中取出之前创建的那个 SurfaceComposerClient 对象
SurfaceComposerClient* client = (SurfaceComposerClient*)env->GetIntField(session, sso.client);
sp surface;//注意它的类型是 SurfaceControl
if (jname == NULL) {
//调用 SurfaceComposerClient 的 createSurface 函数,返回的 surface 是一个 SurfaceControl 类型,这个Surface是为WMS服务的。
surface = client->createSurface(pid, dpy, w, h, format, flags);
} else{
......
}
//把这个 surfaceControl 对象设置到 Java 层的 Surface 对象中,对应mSurfaceControl
setSurfaceControl(env, clazz, surface);
}
很明显看出来,SurfaceComposerClient在这里执行了createSurface方法,要创建Surface. 但是经过上篇我们知道,SurfaceComposerClient最终会通过binder IPC 到Client 最终会在SurfaceFlinger中来执行createSurface:
spSurfaceFlinger::createSurface(ClientID clientId, int pid, const String8& name, ISurfaceFlingerClient::surface_data_t* params, DisplayID d, uint32_t w, uint32_t h, PixelFormat format, uint32_t flags) {
sp layer;//LayerBaseClient 是 Layer 家族的基类
//这里又冒出一个 LayerBaseClient 的内部类,它也叫Surface
sp surfaceHandle;
Mutex::Autolock _l(mStateLock);
//根据 clientId 找到 createConnection 时加入的那个 Client 对象
sp client = mClientsMap.valueFor(clientId);
......
//注意这个 id,它的值表示 Client 创建的是第几个显示层
//同时也表示将使用 SharedBufferStatck 数组的第 id 个元素
int32_t id = client->generateId(pid);
//一个 Client 不能创建多于 NUM_LAYERS_MAX 个的Layer
if(uint32_t(id) >= NUM_LAYERS_MAX) {
return surfaceHandle;
}
//根据 flags 参数来创建不同类型的显示层
switch(flags & eFXSurfaceMask) {
case eFXSurfaceNormal:
if (UNLIKELY(flags & ePushBuffers)) {
//创建 PushBuffer 类型的显示层
layer = createPushBuffersSurfaceLocked(client, d, id, w, h, flags);
} else {
//创建 Normal 类型的显示层
layer = createNormalSurfaceLocked(client, d, id, w, h, flags, format);
}
break;
case eFXSurfaceBlur:
//创建 Blur 类型的显示层
layer = createBlurSurfaceLocked(client, d, id, w, h, flags);
break;
case eFXSurfaceDim:
//创建 Dim 类型的显示层
layer = createDimSurfaceLocked(client, d, id, w, h, flags);
break;
}
if(layer != 0) {
layer->setName(name);
setTransactionFlags(eTransactionNeeded);
//从显示层对象中取出一个 ISurface 对象赋值给 SurfaceHandle
surfaceHandle = layer->getSurface();
if(surfaceHandle != 0) {
params->token = surfaceHandle->getToken();
params->identity = surfaceHandle->getIdentity();
params->width = w;
params->height = h;
params->format = format;
}
}
return surfaceHandle;//ISurface 的 Bn 端就是这个对象
}
在SurfaceFlinger::createSurface方法中,首先根据不同参数创建不同类型的显示层Layer,它是SurfaceFlinger中对Surface的描述,也是合成视图的基本单元。以createNormalSurfaceLocked为例:
spSurfaceFlinger::createNormalSurfaceLocked(const sp& client, DisplayID display, int32_t id, uint32_t w, uint32_t h, uint32_t flags, PixelFormat& format) {
//图像方面的参数设置
switch(format) {
case PIXEL_FORMAT_TRANSPARENT:
case PIXEL_FORMAT_TRANSLUCENT:
format = PIXEL_FORMAT_RGBA_8888;
break;
case PIXEL_FORMAT_OPAQUE:
format = PIXEL_FORMAT_RGB_565;
break;
}
//创建一个 Layer 类型的对象,进去看构造方法,有一些初始工作
sp layer = new Layer(this, display,client, id);
//设置 Buffer
status_t err = layer->setBuffers(w, h, format, flags);
if (LIKELY(err == NO_ERROR)) {
//初始化这个新 layer 的一些状态
layer->initStates(w, h, flags);
//下面这个函数把这个 layer 加入到 Z 轴集合中
addLayer_l(layer);
}
......
return layer;
}
Layer类的成员函数setBuffers就创建了一个SurfaceLayer(像素格式信息)对象,并且保存成员变量mSurface中。initStates初始化这个新 layer 的一些状态,addLayer_l把这个 layer 加入到 Z 轴集合中。
然后返回去看看:surfaceHandle = layer->getSurface();
//Layer
sp Layer::createSurface() const
{
return mSurface;
}
前面我们已经知道了Layer类的成员变量mSurface 就是一个SurfaceLayer对象。这时候SurfaceFlinger服务就完成了Android应用程序所请求创建的Surface了,最后就会将用来描述这个Surface的一个SurfaceLayer对象的一个Binder代理对象返回Android应用程序,以便Android应用程序可以将它封装成一个SurfaceControl对象。
//Surface.cpp
Surface::Surface(const sp& surface)
: mBufferMapper(GraphicBufferMapper::get()),
mClient(SurfaceClient::getInstance()),
mSharedBufferClient(NULL),
mInitCheck(NO_INIT),
mSurface(surface->mSurface),
mIdentity(surface->mIdentity),
mFormat(surface->mFormat), mFlags(surface->mFlags),
mWidth(surface->mWidth), mHeight(surface->mHeight)
{
init();
}
Surface类的成员变量mClient指向了Android应用程序进程中的一个SurfaceClient单例。
Surface类的成员变量mSharedBufferClient指向了一个SharedBufferClient对象。
再看下init():
void Surface::init()
{
//里面设置了一堆成员函数,重点关注dequeueBuffer和queueBuffer
ANativeWindow::setSwapInterval = setSwapInterval;
ANativeWindow::dequeueBuffer = dequeueBuffer;
ANativeWindow::cancelBuffer = cancelBuffer;
ANativeWindow::lockBuffer = lockBuffer;
ANativeWindow::queueBuffer = queueBuffer;
ANativeWindow::query = query;
ANativeWindow::perform = perform;
...
if (mSurface != 0 && mClient.initCheck() == NO_ERROR) {
int32_t token = mClient.getTokenForSurface(mSurface);
if (token >= 0) {
//new 了SharedBufferClient
mSharedBufferClient = new SharedBufferClient(
mClient.getSharedClient(), token, 2, mIdentity);
mInitCheck = mClient.getSharedClient()->validate(token);
}
}
}
看下getTokenForSurface
//UserClient.getTokenForSurface
ssize_t UserClient::getTokenForSurface(const sp& sur) const
{
//token设置相关
...
status_t err = layer->setToken(
const_cast(this), ctrlblk, name);
...
return name;
}
再看下setToken
status_t Layer::setToken(const sp& userClient,
SharedClient* sharedClient, int32_t token)
{
//这里new 了SharedBufferServer
sp lcblk = new SharedBufferServer(
sharedClient, token, mBufferManager.getDefaultBufferCount(),
getIdentity());
status_t err = mUserClientRef.setToken(userClient, lcblk, token);
LOGE_IF(err != NO_ERROR,
"ClientRef::setToken(%p, %p, %u) failed",
userClient.get(), lcblk.get(), token);
if (err == NO_ERROR) {
// we need to free the buffers associated with this surface
}
return err;
}
createSurface一路叉下来分析了很深,总结下:当Android应用程序请求SurfaceFlinger服务创建一个Surface的时候,需要在SurfaceFlinger服务这一侧创建一个Layer对象、一个Layer::SurfaceLayer对象和一个SharedBufferServer对象,同时又需要在Android应用程序这一侧创建一个SurfaceControl对象、一个Surface对象和一个SharedBufferClient对象。这个SurfaceControl最终通过copyFrom返回给客户端。
至于SharedClient、SharedBufferClient、SharedBufferServer会在之后的app与SurfaceFlinger共享UI元数据过程中来分析。
总结:
每一个应用程序窗口都对应有两个Java层的Surface对象,其中一个是在WindowManagerService服务这一侧创建的,而另外一个是在应用程序进程这一侧创建的。在应用程序进程这一侧创建的ava层的Surface在C++层关联有一个Surface对象,用来绘制应用程序窗口的UI,在WindowManagerService服务这一侧创建的Java层的Surface对象在C++层关联有一个SurfaceControl对象,用来设置应用窗口的属性,例如,大小和位置等。为什么需要两个Surface,因为绘制应用程序窗口是独立的,由应用程序进程来完即可,而设置应用程序窗口的属性却需要全局考虑,即需要由WindowManagerService服务来统筹安排,两者必须结合考虑。
应用程序进程是UI绘制表面是通过两个Surface来描述,而在SurfaceFlinger服务内部使用的是一个Layer对象来描述。他们相互对应。
最后附上两张非常好的图,所谓一图胜千言可不是盖的:
Surface创建时序图:
Surface创建过程:
下一节总结下app与SurfaceFlinger共享UI元数据过程
参考:
https://blog.csdn.net/Luoshengyang/article/details/7884628
https://blog.csdn.net/freekiteyu/article/details/79483406