Android图形系统(七)-app请求SurfaceFlinger创建Surface过程

接上篇,WindowManager addView流程来:

ViewRootImpl走setView 我们已经讲了mWindowSession.addToDisplay这条线,app与SurfaceFlinger服务建立了连接,下面我们接着看另外一条线: requestLayout()。

前面我们讲了,requestLayout()开启了绘制流程,具体流程如下图所示:

Android图形系统(七)-app请求SurfaceFlinger创建Surface过程_第1张图片

前三步不啰嗦了,不了解的可以去看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元数据过程中来分析。

总结:

  1. 每一个应用程序窗口都对应有两个Java层的Surface对象,其中一个是在WindowManagerService服务这一侧创建的,而另外一个是在应用程序进程这一侧创建的。在应用程序进程这一侧创建的ava层的Surface在C++层关联有一个Surface对象,用来绘制应用程序窗口的UI,在WindowManagerService服务这一侧创建的Java层的Surface对象在C++层关联有一个SurfaceControl对象,用来设置应用窗口的属性,例如,大小和位置等。为什么需要两个Surface,因为绘制应用程序窗口是独立的,由应用程序进程来完即可,而设置应用程序窗口的属性却需要全局考虑,即需要由WindowManagerService服务来统筹安排,两者必须结合考虑。

  2. 应用程序进程是UI绘制表面是通过两个Surface来描述,而在SurfaceFlinger服务内部使用的是一个Layer对象来描述。他们相互对应。

Android图形系统(七)-app请求SurfaceFlinger创建Surface过程_第2张图片

最后附上两张非常好的图,所谓一图胜千言可不是盖的:

Surface创建时序图:

Android图形系统(七)-app请求SurfaceFlinger创建Surface过程_第3张图片

Surface创建过程:

Android图形系统(七)-app请求SurfaceFlinger创建Surface过程_第4张图片

下一节总结下app与SurfaceFlinger共享UI元数据过程

参考:
https://blog.csdn.net/Luoshengyang/article/details/7884628
https://blog.csdn.net/freekiteyu/article/details/79483406

你可能感兴趣的:(Android图形系统(七)-app请求SurfaceFlinger创建Surface过程)