前面我们分析了:
/*使用代理类,发起跨进程的远程调用,向SurfaceFlinger发起buf申请,导致对方分配内存*/
status_t result = mGraphicBufferProducer->dequeueBuffer(&buf, &fence,reqWidth, reqHeight, reqFormat, reqUsage);
/*先向SurfaceFlinger请求,得到返回文件句柄fd,然后在APP边mmap*/
result = mGraphicBufferProducer->requestBuffer(buf, &gbuf);
中的mGraphicBufferProducer->requestBuffer通过远程调用如何获取buf,在IGraphicBufferProducer.cpp文件中,找到:
class BpGraphicBufferProducer : public BpInterface<IGraphicBufferProducer>
virtual status_t requestBuffer(int bufferIdx, sp<GraphicBuffer>* buf) {
/*构建数据*/
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);
if(result != NO_ERROR) {
(*buf).clear();
return result;
}
}
发起远程调用,会导致BnGraphicBufferProducer中的onTransact被调用,在IGraphicBufferProducer.cpp文件找到onTransact函数:
status_t BnGraphicBufferProducer::onTransact(
/*调用其派生类的requestBuffer,获得sp buffer;*/
int result = requestBuffer(bufferIdx, &buffer);
/*写入binder驱动,最终传递给应用程序*/
reply->write(*buffer);
一个写入binder,一个从binder读出,简单的框图如下:
首先我们来看看,其是如何写入的:
status_t BnGraphicBufferProducer::onTransact(
/*写入binder驱动,最终传递给应用程序*/
reply->write(*buffer);
进入Parcel.cpp文件:
status_t Parcel::write(const FlattenableHelperInterface& val)
/*确定文件句柄有多少个*/
const size_t fd_count = val.getFdCount();
/*该处val为sp buffer;*/
err = val.flatten(buf, len, fds, fd_count);
我们找到GraphicBuffer.cpp中的flatten函数,
status_t GraphicBuffer::flatten(void*& buffer, size_t& size, int*& fds, size_t& count) const {
/*把一些重要的信息填写到buf中*/
......
buf[0] = 'GBFR';
buf[1] = width;
buf[6] = static_cast<int32_t>(mId >> 32);
buf[7] = static_cast<int32_t>(mId & 0xFFFFFFFFull);
buf[8] = static_cast<int32_t>(mGenerationNumber);
......
填充之后通过binder写入。
现在我们来看看读的这边:
class BpGraphicBufferProducer : public BpInterface<IGraphicBufferProducer>
virtual status_t requestBuffer(int bufferIdx, sp<GraphicBuffer>* buf) {
result = reply.read(**buf);
其中read函数也是也是在Parcel.cpp文件中实现:
status_t Parcel::read(FlattenableHelperInterface& val) const
err = val.unflatten(buf, len, fds, fd_count);
其上的unflatten在GraphicBuffer.cpp中实现,与flatten相对应,主要对接收的数据进行判断,使用fd构建一个handle等等:
status_t GraphicBuffer::unflatten(
status_t err = mBufferMapper.registerBuffer(this);
handle中还包含了一个虚拟地址,通过 mBufferMapper.registerBuffer(this)获得。registerBuffer主要是使用fd,然后进行memap,获得虚拟地址。
前面分析应用程序中lock主要会调用一下几个个函数:
当他申请完buf之后,会执行:
sp<GraphicBuffer> backBuffer(GraphicBuffer::getSelf(out));
status_t res = backBuffer->lockAsync(GRALLOC_USAGE_SW_READ_OFTEN | GRALLOC_USAGE_SW_WRITE_OFTEN,newDirtyRegion.bounds(), &vaddr, fenceFd);
我们看看lockAsync如何得到 &vaddr虚拟地址:
status_t res = backBuffer->lockAsync(GRALLOC_USAGE_SW_READ_OFTEN | GRALLOC_USAGE_SW_WRITE_OFTEN,newDirtyRegion.bounds(), &vaddr, fenceFd);
status_t res = getBufferMapper().lockAsync(handle, inUsage, rect, vaddr,fenceFd);
gralloc1_error_t error = mDevice->lock(handle,static_cast<gralloc1_producer_usage_t>(usage),static_cast<gralloc1_consumer_usage_t>(usage),&accessRegion, vaddr, fence);
这样lock函数的分析过程就完成了。