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

    • 3
      点赞
    • 9
      收藏
      觉得还不错? 一键收藏
    • 0
      评论
    评论
    添加红包

    请填写红包祝福语或标题

    红包个数最小为10个

    红包金额最低5元

    当前余额3.43前往充值 >
    需支付:10.00
    成就一亿技术人!
    领取后你会自动成为博主和红包主的粉丝 规则
    hope_wisdom
    发出的红包
    实付
    使用余额支付
    点击重新获取
    扫码支付
    钱包余额 0

    抵扣说明:

    1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
    2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

    余额充值