android—匿名binder

前面的一篇文章《android—binder进程间通讯流程分析》 分析过,service一般都是需要先去service manager注册后,然后才能去使用。而匿名binder就是没有去service manager注册的service,既然没去注册,那么内核中就没有相应的binder_node和binder_ref结构,那么如何使用?下面以BufferQueuemGraphicBufferAlloc对象产生为例。

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去注册。

下面看BpSurfaceComposercreateGraphicBufferAlloc()函数。

    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一次。

你可能感兴趣的:(android—匿名binder)