前面的一篇文章《android—binder进程间通讯流程分析》 分析过,service一般都是需要先去service manager注册后,然后才能去使用。而匿名binder就是没有去service manager注册的service,既然没去注册,那么内核中就没有相应的binder_node和binder_ref结构,那么如何使用?下面以BufferQueue
的mGraphicBufferAlloc
对象产生为例。
BufferQueue::BufferQueue(const sp<IGraphicBufferAlloc>& allocator) :
mDefaultWidth(1),
mDefaultHeight(1),
mMaxAcquiredBufferCount(1),
mDefaultMaxBufferCount(2),
mOverrideMaxBufferCount(0),
mConsumerControlledByApp(false),
mDequeueBufferCannotBlock(false),
mUseAsyncBuffer(true),
mConnectedApi(NO_CONNECTED_API),
mAbandoned(false),
mFrameCounter(0),
mBufferHasBeenQueued(false),
mDefaultBufferFormat(PIXEL_FORMAT_RGBA_8888),
mConsumerUsageBits(0),
mTransformHint(0)
{
// Choose a name using the PID and a process-unique ID.
mConsumerName = String8::format("unnamed-%d-%d", getpid(), createProcessUniqueId());
ST_LOGV("BufferQueue");
if (allocator == NULL) {
//①获取BpSurfaceComposer
sp<ISurfaceComposer> composer(ComposerService::getComposerService());
//②获取mGraphicBufferAlloc
mGraphicBufferAlloc = composer->createGraphicBufferAlloc();
if (mGraphicBufferAlloc == 0) {
ST_LOGE("createGraphicBufferAlloc() failed in BufferQueue()");
}
} else {
mGraphicBufferAlloc = allocator;
}
}
上面BufferQueue
的构造函数中,
首先在①中获取了BpSurfaceComposer,前面有介绍,不展开;
②是获取mGraphicBufferAlloc ,下面详细分析。
sp<IGraphicBufferAlloc> mGraphicBufferAlloc;
从定义看,mGraphicBufferAlloc
应该是GraphicBufferAlloc
服务的代理对象,但是GraphicBufferAlloc
并没有去service manager去注册。
下面看BpSurfaceComposer
的createGraphicBufferAlloc()
函数。
virtual sp<IGraphicBufferAlloc> createGraphicBufferAlloc()
{
uint32_t n;
Parcel data, reply;
data.writeInterfaceToken(ISurfaceComposer::getInterfaceDescriptor());
remote()->transact(BnSurfaceComposer::CREATE_GRAPHIC_BUFFER_ALLOC, data, &reply);
//从reply中,即内核的返回值中readStrongBinder
return interface_cast<IGraphicBufferAlloc>(reply.readStrongBinder());
}
主要的代码就是interface_cast<IGraphicBufferAlloc>(reply.readStrongBinder());
,从reply.readStrongBinder()
中返回BpBinder(handle),然后通过interface_cast<IGraphicBufferAlloc>
转换为BpGraphicBufferAlloc
对象。
那么这个binder对象是如何从server,即surface flinger中传过来的?下面看server端代码,
status_t BnSurfaceComposer::onTransact(
uint32_t code, const Parcel& data, Parcel* reply, uint32_t flags)
{
case CREATE_GRAPHIC_BUFFER_ALLOC: {
CHECK_INTERFACE(ISurfaceComposer, data, reply);
//调用surface flinger的createGraphicBufferAlloc函数
//GraphicBufferAlloc类继承自BnInterface<INTERFACE>
sp<IBinder> b = createGraphicBufferAlloc()->asBinder();
//将binder实体写入
reply->writeStrongBinder(b);
return NO_ERROR;
}
}
sp<IGraphicBufferAlloc> SurfaceFlinger::createGraphicBufferAlloc()
{
//真实的服务是GraphicBufferAlloc
//class GraphicBufferAlloc : public BnGraphicBufferAlloc
sp<GraphicBufferAlloc> gba(new GraphicBufferAlloc());
return gba;
}
GraphicBufferAlloc
类继承自BnInterface<INTERFACE>
,这里调用BnInterface<INTERFACE>
的onAsBinder()
,所以返回的就是GraphicBufferAlloc
new出来的指针。
template<typename INTERFACE>
IBinder* BnInterface<INTERFACE>::onAsBinder()
{
return this;
}
调用reply->writeStrongBinder(b);
,将GraphicBufferAlloc
对象传入内核,这个在前面文章已经介绍过,当将binder实体GraphicBufferAlloc
对象传入内核后,内核会为实体所对应的进程的binder_proc,也就是surface flinger,中创建一个实体对应的binder_node,然后在目标进程,也就是BufferQueue所在的进程中创建一个binder_ref指向前面的binder_node,然后返回给BufferQueue所在的进程一个handle,这个就打通了binder的传递流程。
从上面的分析,得到以下结论:
① service不是必须去service manager中注册后才能去使用;
② 匿名binder必须是建立在一个实名binder之上的,实名binder就是在service manager中注册过的。首先client和server通过实名binder建立联系,然后把匿名binder通过这个实名通道“传递过去”,对方也可以正确获取service的代理对象Bpxxx;
③ 为何需要匿名binder?对于android graphic系统来说,一个Layer对应一个BufferQueue,所以一个应用程序可能会有多个BufferQueue。当BufferQueue构造时,会去surface flinger进程中去创建一个new GraphicBufferAlloc(),所以一个应用程序会在surface flinger进程中创建多个GraphicBufferAlloc对象,我认为匿名Binder一般都是在这种情景中出现的,service有多个实体,在需要使用时,现场创建Binder实体。而一般实名Binder,即是去service manager中注册的service,都只会有一个service实体,即只会new一次。