android-匿名binder

7610 ワード

前の記事「android-binderプロセス間通信プロセス分析」では、サービスは一般的にサービスマネージャに登録してから使用する必要があると分析しています.匿名binderはサービスマネージャに登録されていないサービスであり、登録されていない以上、カーネルには対応する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のコンストラクション関数では、まず1でBpSurfaceComposerを取得し、前に説明があり、展開しません.②はmGraphicBufferAllocを取得し、以下で詳細に分析する.
sp<IGraphicBufferAlloc> mGraphicBufferAlloc;

定義から見ると、mGraphicBufferAllocGraphicBufferAllocサービスのエージェントオブジェクトであるべきであるが、GraphicBufferAllocはサービスマネージャに登録されていない.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(reply.readStrongBinder());であり、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から継承され、ここではBnInterfaceonAsBinder()を呼び出すので、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の伝達プロセスを通じています.上の分析から、以下の結論を得た:1サービスはサービスマネージャに登録してから使用しなければならないわけではない.②匿名binderは実名binderの上に構築されなければならない.実名binderはservice managerに登録されている.まずclientとserverは実名binderを通じて連絡を確立し、匿名binderをこの実名チャネルを通じて「伝達」し、相手もserviceのエージェントBpxxxを正しく取得することができる.③なぜ匿名binderが必要なのか?Android graphicシステムでは、1つのLayerが1つのBufferQueueに対応するため、1つのアプリケーションに複数のBufferQueueがある可能性があります.BufferQueueが構築されると、surface flingerプロセスでnew GraphicBufferAlloc()が作成されるので、1つのアプリケーションはsurface flingerプロセスで複数のGraphicBufferAllocオブジェクトを作成します.匿名Binderは一般的にこのシナリオで発生していると思います.serviceには複数のエンティティがあり、使用する必要がある場合はBinderエンティティを現場で作成します.一般的な実名Binder、すなわちサービスマネージャに登録されているサービスには、サービスエンティティが1つしかありません.つまり、newは1回しかありません.