android 使用SurfaceFlinger 服务的流程分析,基于4.4(一)------SurfaceFlinger 使用步骤

surfaceflinger的使用,可以参考Android 系统源码的 frameworks\native\services\surfaceflinger\tests\resize\resize.cpp 文件,如下:

这虽然是一个c++ 的应用demo,但是android层也是这么用的,也是这么一个流程。只是android 统一用WMS 来对每一个apk做这几步。比如第5步,向buffer里面填充数据,在WMS里面来说就是draw函数,ui的绘制,最终也是向buffer里面填充数据。

 

 

目录

一、new SurfaceComposerClient()

二、createSurface

三、lock

四、unlockAndPost

 

本文只记录关键信息,做个分析笔记。

一般来说应用在使用SurfaceFlinger服务的流程分为以下几步:

一、new SurfaceComposerClient()

创建应用进程的Client ,这个Client 是一个 SurfaceComposerClient 对象,主要用来创建一个surface:

sp<SurfaceComposerClient> client = new SurfaceComposerClient()

其UML 流程图如下:

二、createSurface

①用第一步创建的Client 获得一个surfaceControl 对象,这个surfaceControl 类是用来管理surface的:

sp<SurfaceControl> surfaceControl = client->createSurface(String8("resize"),160, 240, PIXEL_FORMAT_RGB_565, 0);

android wms 里面创建 SurfaceControl 是从调用WindowStateAnimator.createSurfaceLocked()开始的。

            ...
             ↓
windowManagerService.relayoutWindow()
             ↓
WindowStateAnimator.createSurfaceLocked()
             ↓
new SurfaceControl()
             ↓
android_view_SurfaceControl.nativeCreate()
             ↓
sp<SurfaceComposerClient> client(android_view_SurfaceSession_getClient(env, sessionObj)) 
             ↓
sp<SurfaceControl> surface = client->createSurface(...)

②第二步,得到这个surfaceControl 以后,就可以通过 surfaceControl的getSurface 方法拿到当前的一个surface。

sp<Surface> surface = surfaceControl->getSurface();

client->createSurface(...) 和surfaceControl->getSurface() 的UML图见下:

 

那么 wms 在获得了surfaceControl 之后又是怎么获得这个 surface 的呢?

在sp<SurfaceControl> surface = client->createSurface(...) 之后,会返回到wms 里面调用 WindowStateAnimator.createSurfaceLocked() 的地方继续向下执行,就下来的函数流程:

                ...
                 ↓
SurfaceControl surfaceControl = winAnimator.createSurfaceLocked();
outSurface.copyFrom(surfaceControl)
                 ↓
android_view_Surface.nativeCreateFromSurfaceControl(surfaceControlPtr)
                 ↓
sp<SurfaceControl> ctrl(reinterpret_cast<SurfaceControl *>(surfaceControlPtr));
sp<Surface> surface(ctrl->getSurface());
return reinterpret_cast<jint>(surface.get());

通过这样一个流程就拿到底层的surface 了,并把这个surface保存在java层的 surface.java 类(outSurface )里面 mNativeObject  变量里面,最终会把outSurface 返回保存到 ViewRootImpl 类的成员变量 mSurface中,以后就可以执行draw过程了。

 

详细解释:

sp<Surface> surface = surfaceControl->getSurface() ;这句话其实就是在 surfaceControl 类中new 了一个surface 对象,mSurfaceData = new Surface(mGraphicBufferProducer, false) ,这个mGraphicBufferProducer 是从sp<SurfaceControl> surfaceControl = client->createSurface(...)中返回来的,createSurface ()本质是创建一个Layer 对象,这个Layer在创建的时候,就会创建一个生产者mBufferQueue对象 ,mBufferQueue = new SurfaceTextureLayer(mFlinger);其实应用层拿到surface 以后,绘制图像的过程就是在往生产者里面写入东西!所以,surface 里面的mGraphicBufferProducer  对象Layer 里面的 mBufferQueue ,他们就是同一个东西!

三、lock

当我们的应用这边获取到了surface 是不是就可以,绘图了呢?答案是否定的,此时我们虽然有了mGraphicBufferProducer 吧,但是它里面有一个BufferSlot 的结构体见 BufferQueue.h 文件,结构体里面有一个sp<GraphicBuffer> mGraphicBuffer 成员变量,还没有被分配初始化。我们需要对这个成员变量进行分配初始化,这样应用层才会有得到一个应用层的地址,绘图才会往这个地址写内容。那这个过程叫lock,分配buffer!

ANativeWindow_Buffer outBuffer;
surface->lock(&outBuffer, NULL);//分配buffer
ssize_t bpr = outBuffer.stride * bytesPerPixel(outBuffer.format);
android_memset16((uint16_t*)outBuffer.bits, 0xF800, bpr*outBuffer.height);//绘图,往地址里面填入UI信息

surface->lock(&outBuffer, NULL) 这个过程的UML图:

他的内存最终是从android的HAL层的 Gralloc 模块中分配出来的。Gralloc模块,会调用芯片厂商的实现。

那么,android 里面wms ,它里面是怎么去分配buffer的呢?

当应用程序做完 测量(Measure)、布局(Layout) 等流程后,就会跑到 ViewRootImpl.drawSoftware() 软件渲染绘制UI的方法(这里只关注软件渲染ui的流程):如下/**14*/步骤就是渲染绘制的过程。

/**1*/ ApplicationThread的onTransact方法接收到SystemServer进程的SCHEDULE_LAUNCH_ACTIVITY_TRANSACTION启动Activity的Binder信息
                ↓
/**2*/ ApplicationThread.scheduleLaunchActivity() 
                ↓
/**3*/ ActivityThread.scheduleLaunchActivity() //安排启动Activity
                ↓
/**4*/ ActivityThread.handleLaunchActivity()  //处理启动Activity
                ↓
/**5*/ ActivityThread.handleResumeActivity() // Activity 的Resume会使DecorView跟ViewRootImpl关联
                ↓
/**6*/ WindowManagerGlobal.addView() //全局保存窗口的信息
                ↓
/**7*/ ViewRootImpl.setView()  //使DecorView和ViewRootImpl关联并绘制界面
                ↓
/**8*/ ViewRootImpl.requestLayout() //请求绘制ViewTree
                ↓
/**9*/ ViewRootImpl.scheduleTraversals() // 安排遍历 
                ↓
/**10*/ ViewRootImpl.doTraversal() 
                ↓
/**11*/ ViewRootImpl.performTraversals() //执行遍历 会根据情况调用relayoutWindow performMeasure performLayout performDraw 等方法 这四个方法跟绘制是紧密相关的
                ↓
/**12*/ ViewRootImpl.performDraw() //执行绘制
                ↓
/**13*/ ViewRootImpl.draw(boolean fullRedrawNeeded)//区分是否支持硬件加速来走不同的绘制流程 
                ↓
/**14*/ViewRootImpl.drawSoftware() //这里我们就选择软件渲染的流程
                ↓
/**15*/Surface.lockCanvas()
                ↓
/**16*/android_view_Surface.nativeLockCanvas()
                ↓
/**17*/surface.lock(...)  //native 的lock

四、unlockAndPost

当应用程序在申请的surface 上 ,做完绘画以后,就要把buffer 提交给SurfaceFlinger 进程,让其提交给Framebuffer,最终显示,使用的函数是:

surface->unlockAndPost()

其整个UML 图如下:

unlockAndPost 函数调用 queuebuffer 入队列之后,在BufferQueue这一层开始往surfaceflinger 通知消息,可以关注一下UML BufferQueue那一列, 中注释的 listener = mConsumerListener ;这个mConsumerListener 是怎么来的。

回到本文第二章节,在创建createSurface 的时候,本质是创建Layer ,每一个layer对应一个surface。在Layer被创建的时候,layer中的onFirstRef 函数会被调用,如下:

void Layer::onFirstRef() {
    // Creates a custom BufferQueue for SurfaceFlingerConsumer to use
    mBufferQueue = new SurfaceTextureLayer(mFlinger);
    mSurfaceFlingerConsumer = new SurfaceFlingerConsumer(mBufferQueue, mTextureName);
    mSurfaceFlingerConsumer->setConsumerUsageBits(getEffectiveUsage(0));
    mSurfaceFlingerConsumer->setFrameAvailableListener(this);
    mSurfaceFlingerConsumer->setName(mName);
    ......
}

在onFirstRef 函数中会去初始化这个layer中的mBufferQueue成员变量,然后会初始化sp<SurfaceFlingerConsumer> mSurfaceFlingerConsumer 成员变量,SurfaceFlingerConsumer 父类是ConsumerBase ,在构造mSurfaceFlingerConsumer 的同时,会先构造

父类ConsumerBase,在父类里面就创建了 一个 Listener,并把这个Listener,通过mConsumer->consumerConnect(proxy, controlledByApp)赋值给了BufferQueue对象的mConsumerListener 变量!

ConsumerBase::ConsumerBase(const sp<IGraphicBufferConsumer>& bufferQueue, bool controlledByApp) :
        mAbandoned(false),
        mConsumer(bufferQueue) {
             ........
       wp<ConsumerListener> listener = static_cast<ConsumerListener*>(this);
       sp<IConsumerListener> proxy = new BufferQueue::ProxyConsumerListener(listener);    //ConsumerBase 被构造的时候,构造了 ProxyConsumerListener,传递了listener

         status_t err = mConsumer->consumerConnect(proxy, controlledByApp); //放入mConsumerListener
                ...............
    }

所以,当BufferQueue对象拿到了mConsumerListener 变量,那么以后在queuebuffer过程中,把buffer入队以后,就可以通过 mConsumerListener 一层一层的通知surfaceflinger 了。

最终是调用到surfaceflinger 的 signalLayerUpdate 函数,进行通知。后面surfaceflinger是怎么处理buffer 的数据的,以后再做分析。

 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值