android—匿名binder
前面的一篇文章《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
,从reply.readStrongBinder()
中返回BpBinder(handle),然后通过interface_cast
转换为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 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
,这里调用BnInterface
的onAsBinder()
,所以返回的就是GraphicBufferAlloc
new出来的指针。
template<typename INTERFACE>IBinder* BnInterface::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一次。
更多相关文章
- Android(安卓)Material Design Snackbar Example
- Android(安卓)TextView当中设置超链接、颜色、字体
- Android(安卓)XML小工具
- android persistent属性研究
- android开发两种退出程序方式(killProcess,System.exit)
- ActivityManagerService启动流程详解
- Android消息机制(Handler、Looper、MessageQueue)
- Android的Application对象讲解
- 阿里架构师最新整理 Android(安卓)面试点梳理,你收藏了吗?