在Android中,BufferQueue是Surface实现本地窗口的关键,驻留在SurfaceFlinger进程中进行服务,下面从BufferQueue的结构开始分析,

class BufferQueue : public BnGraphicBufferProducer,                    public BnGraphicBufferConsumer,                    private IBinder::DeathRecipient {

可见BufferQueue拥有producer和consumer两端。再看看createBufferQueue的实现,这里创建了一个BufferQueueCore,然后以这个为参数依次创建了BufferQueueProducer和BufferQueueConsumer。

void BufferQueue::createBufferQueue(sp* outProducer,        sp* outConsumer,        const sp& allocator) {    sp core(new BufferQueueCore(allocator));    sp producer(new BufferQueueProducer(core));    sp consumer(new BufferQueueConsumer(core));    *outProducer = producer;    *outConsumer = consumer;}

这里的producer和consumer是要设置的,而allocator是从外面传进来的,如果传NULL,则在BufferQueueCore中会初始化,如下:

BufferQueueCore::BufferQueueCore(const sp& allocator) {    if (allocator == NULL) {        sp composer(ComposerService::getComposerService());        mAllocator = composer->createGraphicBufferAlloc();    }}

这里的ISurfaceComposer实现在SurfaceFlinger中,再看createGraphicBufferAlloc的实现:

sp SurfaceFlinger::createGraphicBufferAlloc() {    sp gba(new GraphicBufferAlloc());    return gba;}

这个GraphicBufferAlloc构造函数是个空壳,看看createGraphicBuffer的实现,

sp GraphicBufferAlloc::createGraphicBuffer(uint32_t width,        uint32_t height, PixelFormat format, uint32_t usage, status_t* error) {    sp graphicBuffer(            new GraphicBuffer(width, height, format, usage));    status_t err = graphicBuffer->initCheck();    return graphicBuffer;}

GraphicBuffer继承自ANativeWindowBuffer,这个定义在window.h中,值得注意的是里面有个buffer_handle_t句柄,用于共享内存映射的文件句柄就保存在里面了。GraphicBuffer实现了Flattenable接口从而可以跨进程传输。GraphicBuffer构造函数中调用initSize开辟内存,

status_t GraphicBuffer::initSize(uint32_t inWidth, uint32_t inHeight,        PixelFormat inFormat, uint32_t inUsage) {    GraphicBufferAllocator& allocator = GraphicBufferAllocator::get();    status_t err = allocator.alloc(inWidth, inHeight, inFormat, inUsage,            &handle, &outStride);    ......    return err;}

这里又冒出来一个GraphicBufferAllocator类,注意和之前的GraphicBufferAlloc是两回事,这里是真正创建内存了。这个allocator是个单例,构造函数中加载Gralloc模块。具体的alloc应该会跟平台相关了。

GraphicBufferAllocator::GraphicBufferAllocator() : mAllocDev(0) {    hw_module_t const* module;    int err = hw_get_module(GRALLOC_HARDWARE_MODULE_ID, &module);    if (err == 0) {        gralloc_open(module, &mAllocDev);    }}status_t GraphicBufferAllocator::alloc(uint32_t width, uint32_t height,        PixelFormat format, uint32_t usage, buffer_handle_t* handle,        uint32_t* stride) {    err = mAllocDev->alloc(mAllocDev, static_cast(width),            static_cast(height), format, static_cast(usage), handle,            &outStride);    ......    return err;}

到这里整个BufferQueue的创建就大致清楚了,其核心是GraphicBuffer的Allocator,最终是调用的Gralloc模块来开辟GraphicBuffer。

搜索一下BufferQueue在哪些地方被创建的,有以下几处,

  1. SurfaceTexture初始化时
  2. SurfaceFlinger初始化时,为每个显示器创建一个BufferQueue
  3. Layer创建时的onFirstRef中

我们重点关注Surface,这是应用端和SurfaceFlinger交互的关键了,SurfaceTexture和Layer都和Surface有千丝万缕的联系。

接下来分析BufferQueueProducer,下面是dequeueBuffer函数,首先找空闲的slot,如果buffer需要重新分配则创建GraphicBuffer设置到mSlots中。

status_t BufferQueueProducer::dequeueBuffer(int *outSlot, ...) {    int found = BufferItem::INVALID_BUFFER_SLOT;    while (found == BufferItem::INVALID_BUFFER_SLOT) {        status_t status = waitForFreeSlotThenRelock(FreeSlotCaller::Dequeue, &found);        const sp& buffer(mSlots[found].mGraphicBuffer);    }    const sp& buffer(mSlots[found].mGraphicBuffer);    *outSlot = found;    ......    if (returnFlags & BUFFER_NEEDS_REALLOCATION) {        sp graphicBuffer = new GraphicBuffer(...);        ......        mSlots[*outSlot].mGraphicBuffer = graphicBuffer;    }    return returnFlags;}

我们再来看Surface中的dequeueBuffer,Surface作为BufferQueue的client端,其mGraphicBufferProducer必定是IGraphicBufferProducer的Bp端,对应的Bn端在BufferQueue中。这里通过dequeueBuffer后,先判断Buffer是否在BufferQueue端重新分配过了,如果是则需要调用requestBuffer刷新本地的GraphicBuffer。

int Surface::dequeueBuffer(android_native_buffer_t** buffer, int* fenceFd) {    status_t result = mGraphicBufferProducer->dequeueBuffer(&buf, &fence,            reqWidth, reqHeight, reqFormat, reqUsage,            enableFrameTimestamps ? &frameTimestamps : nullptr);    sp& gbuf(mSlots[buf].buffer);    if ((result & IGraphicBufferProducer::BUFFER_NEEDS_REALLOCATION) || gbuf == nullptr) {        result = mGraphicBufferProducer->requestBuffer(buf, &gbuf);    }    *buffer = gbuf.get();    return OK;}

这里的问题是Surface和BufferQueue运行于不同的进程,其GraphicBuffer是否指向同一块物理内存。我们分析requestBuffer函数,我们首先看BpGraphicBufferProducer的transact,这里首先IPC调用REQUEST_BUFFER,获取到reply,然后本地先创建一个GraphicBuffer空壳,再从reply中将真正的数据读进来。

// IGraphicBufferProducer.cpp virtual status_t requestBuffer(int bufferIdx, sp* buf) {    Parcel data, reply;    data.writeInterfaceToken(IGraphicBufferProducer::getInterfaceDescriptor());    data.writeInt32(bufferIdx);    status_t result =remote()->transact(REQUEST_BUFFER, data, &reply);    bool nonNull = reply.readInt32();    if (nonNull) {        *buf = new GraphicBuffer();        result = reply.read(**buf);    }    result = reply.readInt32();    return result;}

再来看BnGraphicBufferProducer的onTransact,

case REQUEST_BUFFER: {    CHECK_INTERFACE(IGraphicBufferProducer, data, reply);    int bufferIdx   = data.readInt32();    sp buffer;    int result = requestBuffer(bufferIdx, &buffer);    reply->writeInt32(buffer != 0);    if (buffer != 0) {        reply->write(*buffer);    }    reply->writeInt32(result);    return NO_ERROR;}

这里会调用GraphicBufferProducer中的requestBuffer,然后将buffer写入reply中。可见GraphicBuffer可以通过Binder传递,

class GraphicBuffer    : public ANativeObjectBase,      public Flattenable

原来这里实现了Flattenable,实现这个接口的对象可以序列化到buffer中,包括其中的文件描述符。我们看其unflatten实现,这里的fds很可能已经变了,这里关键是registerBuffer,很可能是要开始映射内存了。这个mBufferMapper是GraphicBufferMapper,

status_t GraphicBuffer::unflatten(        void const*& buffer, size_t& size, int const*& fds, size_t& count) {    ......    if (handle != 0) {        status_t err = mBufferMapper.registerBuffer(handle);        ......    }    ......    return NO_ERROR;}

再来看GraphicBufferMapper的实现,在构造函数中加载了Gralloc模块,看来是平台相关的。到这里有点眼熟,之前提到的GraphicBufferAllocator初始化时也会加载Gralloc模块,那是在SurfaceFlinger中真正创建GraphicBuffer用的,而这里应用端只需将句柄映射到自己的内存空间即可,所以有了这个GraphicBufferMapper。

GraphicBufferMapper::GraphicBufferMapper() : mAllocMod(0) {    hw_module_t const* module;    int err = hw_get_module(GRALLOC_HARDWARE_MODULE_ID, &module);    if (err == 0) {        mAllocMod = (gralloc_module_t const *) module;    }}status_t GraphicBufferMapper::registerBuffer(buffer_handle_t handle) {    status_t err;    err = mAllocMod->registerBuffer(mAllocMod, handle);    return err;}

这里的registerBuffer是和平台相关的,我们看msm8960平台的实现:

gralloc_register_buffer(gralloc_module_t const* module,     buffer_handle_t handle) {    private_handle_t* hnd = (private_handle_t*)handle;    hnd->base = 0;    hnd->base_metadata = 0;    int err = gralloc_map(module, handle);    return 0;}

这里调用了gralloc_map将handle句柄映射到自己的进程空间,而这块区域与BufferQueue中指向的物理空间是一致的,从而实现了两者跨进程缓冲区共享。

到这里我们大致明白了本地Surface和对端BufferQueue之间的dequeueBuffer时的过程,接下来我们了解一下Surface是怎么和BufferQueue建立联系的。

我们在本文开头提到,在Layer创建时的onFirstRef中会createBufferQueue,而Layer的创建在SurfaceFlinger中的createLayer函数,而这个函数被Client的createSurface调用,这个Client是BnSurfaceComposerClient的子类,因此其中包含createSurface的实现,我们注意到里面会将所有Bp端发起的createSurface请求串行化后再丢给SurfaceFlinger。

再看BpSurfaceComposerClient中的createSurface是被谁调到的,我们发现SurfaceControl中的nativeCreate时会调到,这是SurfaceControl的构造函数中调到的。

// android_view_SurfaceControl.cppstatic jint nativeCreate(JNIEnv* env, jclass clazz, jobject sessionObj,    jstring nameStr, jint w, jint h, jint format, jint flags) {    sp client(android_view_SurfaceSession_getClient(env, sessionObj));    sp surface = client->createSurface(        String8(name.c_str()), w, h, format, flags);    surface->incStrong((void *)nativeCreate);    return int(surface.get());}

这里createSurface返回的是SurfaceControl,这个其实是SurfaceComposerClient封装了一层,将远端返回的Binder句柄和GraphicBufferProducer都封装起来了,所以通过SurfaceControl可以和SurfaceFlinger通信。再看nativeCreate中通过android_view_SurfaceSession_getClient获取SurfaceComposerClient,看看SurfaceSession是什么,这个是连接到SurfaceFlinger的,Java类中保存了一个long型的mNativeClient,这在Native层对应着SurfaceComposerClient。

public final class SurfaceSession {    // Note: This field is accessed by native code.    private long mNativeClient; // SurfaceComposerClient*    private static native long nativeCreate();    private static native long nativeCreateScoped(long surfacePtr);    private static native void nativeDestroy(long ptr);    private static native void nativeKill(long ptr);    /** Create a new connection with the surface flinger. */    public SurfaceSession() {        mNativeClient = nativeCreate();    }    ......}

再看Native层实现:

static jlong nativeCreate(JNIEnv* env, jclass clazz) {    SurfaceComposerClient* client = new SurfaceComposerClient();    client->incStrong((void*)nativeCreate);    return reinterpret_cast(client);}

这里创建了一个SurfaceComposerClient,并没有看到连到SurfaceFlinger端,看其构造函数也没有,我们想到onFirstRef,

void SurfaceComposerClient::onFirstRef() {    sp sm(ComposerService::getComposerService());    if (sm != 0) {        auto rootProducer = mParent.promote();        sp conn;        conn = sm->createConnection();        if (conn != 0) {            mClient = conn;            mStatus = NO_ERROR;        }    }}

到这里就清楚了,ISurfaceComposer是个与SurfaceFlinger通信的Binder句柄,通过该句柄的createConnection可以获取ISurfaceComposerClient,而SurfaceComposerClient是在其基础上包装了一层而已。

所以本地应用需要通过SurfaceSession建立和SurfaceFlinger连接,获取SurfaceComposerClient,然后再通过这个句柄调用createSurface,返回GraphicBufferProducer,封装到SurfaceControl中,有了这个GraphicBufferProducer接下来就好办了。

更多相关文章

  1. C语言函数以及函数的使用
  2. android kernel 初始化 1
  3. android 回调函数二:应用实例
  4. Android 5.0 Input初始化
  5. Android 5.0 Phone初始化分析
  6. Android 5.0 Telephony关键类初始化和相互关系

随机推荐

  1. Eclipse插件svn和TortoiseSvn版本对应关
  2. Android(安卓)ORMLite框架笔记
  3. Android(安卓)引入第三方so后启动报错 /l
  4. 【免费讲座】3G/嵌入式/物联网/云计算
  5. Android(安卓)用户自定义对话框
  6. Android(安卓)使用自定义SVG
  7. Android(安卓)指定SD卡上一首歌作为程序
  8. android UiAutomator自定义快速调试类
  9. Android(安卓)用adb pull或push 拷贝手机
  10. Android登录功能实现